
#include "yoshix.h"

#include "d3d10.h"
#include "d3dx10.h"

#include <assert.h>
#include <exception>
#include <iostream>
#include <new.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <windowsx.h>

#define UNUSED(Argument) ((void) &Argument)

#define SAFE_RELEASE(Resource) { if (Resource) { (Resource)->Release(); (Resource) = 0; } }

////////////////////////////////////////////////////////////////////////////////
/// \typedef gfx::BHandle
///
/// \brief Handle to an internal resource of the YoshiX frame work.
///
/// Handle to an internal resource of the YoshiX frame work.
/// 
/// \warning Do not forget to release created resources again.
////////////////////////////////////////////////////////////////////////////////
using namespace gfx;

namespace
{
    const float g_Pi = 3.1415926535897932384626433832795f;
} // namespace gfx

namespace
{
    const char g_Shader[] =
    {
        // -----------------------------------------------------------------------------
        // Constant buffer.
        // -----------------------------------------------------------------------------

        "   cbuffer SPerFrameVSBuffer                                                                                                       "
        "   {                                                                                                                               "
        "       float3   g_EyePosition;                                                                                                     "
        "       float    Padding1;                                                                                                          "
        "       float3   g_LightPosition;                                                                                                   "
        "       float    Padding2;                                                                                                          "
        "       float4x4 g_ViewProjectionMatrix;                                                                                            "
        "   };                                                                                                                              "

        "   cbuffer SPerFramePSBuffer                                                                                                       "
        "   {                                                                                                                               "
        "       float4   g_LightAmbientColor;                                                                                               "
        "       float4   g_LightDiffuseColor;                                                                                               "
        "       float4   g_LightSpecularColor;                                                                                              "
        "       float    g_LightSpecularExponent;                                                                                           "
        "       float3   Padding3;                                                                                                          "
        "   };                                                                                                                              "

        "   cbuffer SPerDrawCallVSBuffer                                                                                                    "
        "   {                                                                                                                               "
        "       float4x4 g_WorldMatrix;                                                                                                     "
        "   };                                                                                                                              "

        // -----------------------------------------------------------------------------
        // Color texture.
        // -----------------------------------------------------------------------------

        "   Texture2D g_ColorMap : register(t[0]);                                                                                          "

        // -----------------------------------------------------------------------------
        // Color texture sampler.
        // -----------------------------------------------------------------------------

        "   sampler g_ColorMapSampler : register(s[0]);                                                                                     "   

        // -----------------------------------------------------------------------------
        // Default material.
        // -----------------------------------------------------------------------------

        "   struct VSDefaultInput                                                                                                           "
        "   {                                                                                                                               "
        "       float3 m_Position : POSITION;                                                                                               "
        "   };                                                                                                                              "

        "   struct PSDefaultInput                                                                                                           "
        "   {                                                                                                                               "
        "       float4 m_Position : SV_POSITION;                                                                                            "
        "   };                                                                                                                              "

        "   PSDefaultInput VSDefaultShader(VSDefaultInput _Input)                                                                           "
        "   {                                                                                                                               "
        "       PSDefaultInput Output;                                                                                                      "
        "       float4         WSPosition;                                                                                                  "
        "                                                                                                                                   "
        "       Output            = (PSDefaultInput) 0;                                                                                     "
        "                                                                                                                                   "
        "       WSPosition        = mul(g_WorldMatrix, float4(_Input.m_Position, 1.0f));                                                    "
        "                                                                                                                                   "
        "       Output.m_Position = mul(g_ViewProjectionMatrix, WSPosition);                                                                "
        "                                                                                                                                   "
        "       return Output;                                                                                                              "
        "   }                                                                                                                               "

        "   float4 PSDefaultShader(PSDefaultInput _Input) : SV_Target                                                                       "
        "   {                                                                                                                               "
        "       return float4(0.5f, 0.5f, 0.5f, 1.0f);                                                                                      "
        "   }                                                                                                                               "

        // -----------------------------------------------------------------------------
        // Default illuminated material.
        // -----------------------------------------------------------------------------

        "   struct VSDefaultIllInput                                                                                                        "
        "   {                                                                                                                               "
        "       float3 m_Position : POSITION;                                                                                               "
        "       float3 m_Normal   : NORMAL;                                                                                                 "
        "   };                                                                                                                              "

        "   struct PSDefaultIllInput                                                                                                        "
        "   {                                                                                                                               "
        "       float4 m_Position : SV_POSITION;                                                                                            "
        "       float3 m_Normal   : NORMAL;                                                                                                 "
        "       float3 m_ViewDir  : TEXCOORD0;                                                                                              "
        "       float3 m_LightDir : TEXCOORD1;                                                                                              "
        "   };                                                                                                                              "

        "   PSDefaultIllInput VSDefaultIllShader(VSDefaultIllInput _Input)                                                                  "
        "   {                                                                                                                               "
        "       PSDefaultIllInput Output;                                                                                                   "
        "       float4            WSPosition;                                                                                               "
        "                                                                                                                                   "
        "       Output            = (PSDefaultIllInput) 0;                                                                                  "
        "                                                                                                                                   "
        "       WSPosition        = mul(g_WorldMatrix, float4(_Input.m_Position, 1.0f));                                                    "
        "                                                                                                                                   "
        "       Output.m_Position = mul(g_ViewProjectionMatrix, WSPosition);                                                                "
        "       Output.m_Normal   = mul(g_WorldMatrix, float4(_Input.m_Normal, 0)).xyz;                                                     "
        "       Output.m_ViewDir  = g_EyePosition   - WSPosition.xyz;                                                                       "
        "       Output.m_LightDir = g_LightPosition - WSPosition.xyz;                                                                       "
        "                                                                                                                                   "
        "       return Output;                                                                                                              "
        "   }                                                                                                                               "

        "   float4 PSDefaultIllShader(PSDefaultIllInput _Input) : SV_Target                                                                 "
        "   {                                                                                                                               "
        "       float  NDotH;                                                                                                               "
        "       float3 Normal;                                                                                                              "
        "       float3 ViewDir;                                                                                                             "
        "       float3 LightDir;                                                                                                            "
        "       float3 HalfDir;                                                                                                             "
        "       float4 MaterialColor;                                                                                                       "
        "       float4 LightAmbientIntensity;                                                                                               "
        "       float4 LightDiffuseIntensity;                                                                                               "
        "       float4 LightSpecularIntensity;                                                                                              "
        "                                                                                                                                   "
        "       MaterialColor          = float4(0.5f, 0.5f, 0.5f, 1.0f);                                                                    "
        "                                                                                                                                   "
        "       Normal                 = normalize(_Input.m_Normal);                                                                        "
        "       ViewDir                = normalize(_Input.m_ViewDir);                                                                       "
        "       LightDir               = normalize(_Input.m_LightDir);                                                                      "
        "       HalfDir                = normalize(ViewDir + LightDir);                                                                     "
        "                                                                                                                                   "
        "       LightAmbientIntensity  = g_LightAmbientColor;                                                                               "
        "       LightDiffuseIntensity  = max(0.0f, dot(LightDir, Normal)) * g_LightDiffuseColor;                                            "
        "       LightSpecularIntensity = max(0.0f, pow(max(0.0f, dot(Normal, HalfDir)), g_LightSpecularExponent)) * g_LightSpecularColor;   "
        "                                                                                                                                   "
        "       return (LightAmbientIntensity + LightDiffuseIntensity + LightSpecularIntensity) * MaterialColor;                            "
        "   }                                                                                                                               "

        // -----------------------------------------------------------------------------
        // Colored material.
        // -----------------------------------------------------------------------------

        "   struct VSColInput                                                                                                               "
        "   {                                                                                                                               "
        "       float3 m_Position : POSITION;                                                                                               "
        "       float4 m_Color    : COLOR;                                                                                                  "
        "   };                                                                                                                              "

        "   struct PSColInput                                                                                                               "
        "   {                                                                                                                               "
        "       float4 m_Position : SV_POSITION;                                                                                            "
        "       float4 m_Color    : COLOR0;                                                                                                 "
        "   };                                                                                                                              "

        "   PSColInput VSColShader(VSColInput _Input)                                                                                       "
        "   {                                                                                                                               "
        "       PSColInput Output;                                                                                                          "
        "       float4     WSPosition;                                                                                                      "
        "                                                                                                                                   "
        "       Output            = (PSColInput) 0;                                                                                         "
        "                                                                                                                                   "
        "       WSPosition        = mul(g_WorldMatrix, float4(_Input.m_Position, 1.0f));                                                    "
        "                                                                                                                                   "
        "       Output.m_Position = mul(g_ViewProjectionMatrix, WSPosition);                                                                "
        "       Output.m_Color    = _Input.m_Color;                                                                                         "
        "                                                                                                                                   "
        "       return Output;                                                                                                              "
        "   }                                                                                                                               "

        "   float4 PSColShader(PSColInput _Input) : SV_Target                                                                               "
        "   {                                                                                                                               "
        "       return _Input.m_Color;                                                                                                      "
        "   }                                                                                                                               "

        // -----------------------------------------------------------------------------
        // Colored illuminated material.
        // -----------------------------------------------------------------------------

        "   struct VSColIllInput                                                                                                            "
        "   {                                                                                                                               "
        "       float3 m_Position : POSITION;                                                                                               "
        "       float3 m_Normal   : NORMAL;                                                                                                 "
        "       float4 m_Color    : COLOR;                                                                                                  "
        "   };                                                                                                                              "

        "   struct PSColIllInput                                                                                                            "
        "   {                                                                                                                               "
        "       float4 m_Position : SV_POSITION;                                                                                            "
        "       float3 m_Normal   : NORMAL;                                                                                                 "
        "       float4 m_Color    : COLOR0;                                                                                                 "
        "       float3 m_ViewDir  : TEXCOORD0;                                                                                              "
        "       float3 m_LightDir : TEXCOORD1;                                                                                              "
        "   };                                                                                                                              "

        "   PSColIllInput VSColIllShader(VSColIllInput _Input)                                                                              "
        "   {                                                                                                                               "
        "       PSColIllInput Output;                                                                                                       "
        "       float4        WSPosition;                                                                                                   "
        "                                                                                                                                   "
        "       Output            = (PSColIllInput) 0;                                                                                      "
        "                                                                                                                                   "
        "       WSPosition        = mul(g_WorldMatrix, float4(_Input.m_Position, 1.0f));                                                    "
        "                                                                                                                                   "
        "       Output.m_Position = mul(g_ViewProjectionMatrix, WSPosition);                                                                "
        "       Output.m_Normal   = mul(g_WorldMatrix, float4(_Input.m_Normal, 0)).xyz;                                                     "
        "       Output.m_Color    = _Input.m_Color;                                                                                         "
        "       Output.m_ViewDir  = g_EyePosition   - WSPosition.xyz;                                                                       "
        "       Output.m_LightDir = g_LightPosition - WSPosition.xyz;                                                                       "
        "                                                                                                                                   "
        "       return Output;                                                                                                              "
        "   }                                                                                                                               "

        "   float4 PSColIllShader(PSColIllInput _Input) : SV_Target                                                                         "
        "   {                                                                                                                               "
        "       float  NDotH;                                                                                                               "
        "       float3 Normal;                                                                                                              "
        "       float3 ViewDir;                                                                                                             "
        "       float3 LightDir;                                                                                                            "
        "       float3 HalfDir;                                                                                                             "
        "       float4 LightAmbientIntensity;                                                                                               "
        "       float4 LightDiffuseIntensity;                                                                                               "
        "       float4 LightSpecularIntensity;                                                                                              "
        "                                                                                                                                   "
        "       Normal                 = normalize(_Input.m_Normal);                                                                        "
        "       ViewDir                = normalize(_Input.m_ViewDir);                                                                       "
        "       LightDir               = normalize(_Input.m_LightDir);                                                                      "
        "       HalfDir                = normalize(ViewDir + LightDir);                                                                     "
        "                                                                                                                                   "
        "       LightAmbientIntensity  = g_LightAmbientColor;                                                                               "
        "       LightDiffuseIntensity  = max(0.0f, dot(LightDir, Normal)) * g_LightDiffuseColor;                                            "
        "       LightSpecularIntensity = max(0.0f, pow(max(0.0f, dot(Normal, HalfDir)), g_LightSpecularExponent)) * g_LightSpecularColor;   "
        "                                                                                                                                   "
        "       return (LightAmbientIntensity + LightDiffuseIntensity + LightSpecularIntensity) * _Input.m_Color;                           "
        "   }                                                                                                                               "

        // -----------------------------------------------------------------------------
        // Texture Material
        // -----------------------------------------------------------------------------

        "   struct VSTexInput                                                                                                               "
        "   {                                                                                                                               "
        "       float3 m_Position : POSITION;                                                                                               "
        "       float2 m_TexCoord : TEXCOORD;                                                                                               "
        "   };                                                                                                                              "

        "   struct PSTexInput                                                                                                               "
        "   {                                                                                                                               "
        "       float4 m_Position : SV_POSITION;                                                                                            "
        "       float2 m_TexCoord : TEXCOORD0;                                                                                              "
        "   };                                                                                                                              "

        "   PSTexInput VSTexShader(VSTexInput _Input)                                                                                       "
        "   {                                                                                                                               "
        "       PSTexInput Output;                                                                                                          "
        "       float4     WSPosition;                                                                                                      "
        "                                                                                                                                   "
        "       Output            = (PSTexInput) 0;                                                                                         "
        "                                                                                                                                   "
        "       WSPosition        = mul(g_WorldMatrix, float4(_Input.m_Position, 1.0f));                                                    "
        "                                                                                                                                   "
        "       Output.m_Position = mul(g_ViewProjectionMatrix, WSPosition);                                                                "
        "       Output.m_TexCoord = _Input.m_TexCoord;                                                                                      "
        "                                                                                                                                   "
        "       return Output;                                                                                                              "
        "   }                                                                                                                               "

        "   float4 PSTexShader(PSTexInput _Input) : SV_Target                                                                               "
        "   {                                                                                                                               "
        "       return g_ColorMap.Sample(g_ColorMapSampler, _Input.m_TexCoord);                                                             "
        "   }                                                                                                                               "

        // -----------------------------------------------------------------------------
        // Textured illuminated material.
        // -----------------------------------------------------------------------------

        "   struct VSTexIllInput                                                                                                            "
        "   {                                                                                                                               "
        "       float3 m_Position : POSITION;                                                                                               "
        "       float3 m_Normal   : NORMAL;                                                                                                 "
        "       float2 m_TexCoord : TEXCOORD;                                                                                               "
        "   };                                                                                                                              "

        "   struct PSTexIllInput                                                                                                            "
        "   {                                                                                                                               "
        "       float4 m_Position : SV_POSITION;                                                                                            "
        "       float3 m_Normal   : NORMAL;                                                                                                 "
        "       float2 m_TexCoord : TEXCOORD0;                                                                                              "
        "       float3 m_ViewDir  : TEXCOORD1;                                                                                              "
        "       float3 m_LightDir : TEXCOORD2;                                                                                              "
        "   };                                                                                                                              "

        "   PSTexIllInput VSTexIllShader(VSTexIllInput _Input)                                                                              "
        "   {                                                                                                                               "
        "       PSTexIllInput Output;                                                                                                       "
        "       float4        WSPosition;                                                                                                   "
        "                                                                                                                                   "
        "       Output            = (PSTexIllInput) 0;                                                                                      "
        "                                                                                                                                   "
        "       WSPosition        = mul(g_WorldMatrix, float4(_Input.m_Position, 1.0f));                                                    "
        "                                                                                                                                   "
        "       Output.m_Position = mul(g_ViewProjectionMatrix, WSPosition);                                                                "
        "       Output.m_Normal   = mul(g_WorldMatrix, float4(_Input.m_Normal, 0)).xyz;                                                     "
        "       Output.m_TexCoord = _Input.m_TexCoord;                                                                                      "
        "       Output.m_ViewDir  = g_EyePosition   - WSPosition.xyz;                                                                       "
        "       Output.m_LightDir = g_LightPosition - WSPosition.xyz;                                                                       "
        "                                                                                                                                   "
        "       return Output;                                                                                                              "
        "   }                                                                                                                               "

        "   float4 PSTexIllShader(PSTexIllInput _Input) : SV_Target                                                                         "
        "   {                                                                                                                               "
        "       float  NDotH;                                                                                                               "
        "       float3 Normal;                                                                                                              "
        "       float3 ViewDir;                                                                                                             "
        "       float3 LightDir;                                                                                                            "
        "       float3 HalfDir;                                                                                                             "
        "       float4 MaterialColor;                                                                                                       "
        "       float4 LightAmbientIntensity;                                                                                               "
        "       float4 LightDiffuseIntensity;                                                                                               "
        "       float4 LightSpecularIntensity;                                                                                              "
        "                                                                                                                                   "
        "       MaterialColor          = g_ColorMap.Sample(g_ColorMapSampler, _Input.m_TexCoord);                                           "
        "                                                                                                                                   "
        "       Normal                 = normalize(_Input.m_Normal);                                                                        "
        "       ViewDir                = normalize(_Input.m_ViewDir);                                                                       "
        "       LightDir               = normalize(_Input.m_LightDir);                                                                      "
        "       HalfDir                = normalize(ViewDir + LightDir);                                                                     "
        "                                                                                                                                   "
        "       LightAmbientIntensity  = g_LightAmbientColor;                                                                               "
        "       LightDiffuseIntensity  = max(0.0f, dot(LightDir, Normal)) * g_LightDiffuseColor;                                            "
        "       LightSpecularIntensity = max(0.0f, pow(max(0.0f, dot(Normal, HalfDir)), g_LightSpecularExponent)) * g_LightSpecularColor;   "
        "                                                                                                                                   "
        "       return (LightAmbientIntensity + LightDiffuseIntensity + LightSpecularIntensity) * MaterialColor;                            "
        "   }                                                                                                                               "
    };
} // namespace

namespace
{
    void WriteErrorMessage(const char* _pMessage)
    {
        std::cout << "Error: " << _pMessage << std::endl;
    }
} // namespace

namespace
{
    struct SPerFrameVSBuffer
    {
        D3DXVECTOR3 m_EyePosition;
        float       m_Padding1;
        D3DXVECTOR3 m_LightPosition;
        float       m_Padding2;
        D3DXMATRIX  m_ViewProjectionMatrix;
    };

    struct SPerFramePSBuffer
    {
        D3DXCOLOR m_LightAmbientColor;
        D3DXCOLOR m_LightDiffuseColor;
        D3DXCOLOR m_LightSpecularColor;
        float     m_LightSpecularExponent;
        float     m_Padding1[3];
    };

    struct SPerDrawCallVSBuffer
    {
        D3DXMATRIX m_WorldMatrix;
    };
} // namespace

namespace
{
    struct SLight
    {
        D3DXVECTOR3 m_Position;
        float       m_LightSpecularExponent;
        D3DXCOLOR   m_AmbientColor;
        D3DXCOLOR   m_DiffuseColor;
        D3DXCOLOR   m_SpecularColor;
    };
} // namespace

namespace
{
    template <typename TTargetPtr, typename TSourcePtr>
    TTargetPtr AddToPtr(TSourcePtr* _pPtr, unsigned long _NumberOfBytes)
    {
        return reinterpret_cast<TTargetPtr>(reinterpret_cast<unsigned long>(_pPtr) + _NumberOfBytes);
    }

    // -----------------------------------------------------------------------------

    template <typename TTargetPtr, typename TSourcePtr>
    TTargetPtr SubFromPtr(TSourcePtr* _pPtr, unsigned long _NumberOfBytes)
    {
        return reinterpret_cast<TTargetPtr>(reinterpret_cast<unsigned long>(_pPtr) - _NumberOfBytes);
    }

    // -----------------------------------------------------------------------------

    template <typename TUnit, typename TStartPtr, typename TEndPtr>
    size_t DistanceOfPtr(TEndPtr* _pEndPtr, TStartPtr* _pStartPtr)
    {
        assert(reinterpret_cast<unsigned long>(_pEndPtr) >= reinterpret_cast<unsigned long>(_pStartPtr));

        return (reinterpret_cast<unsigned long>(_pEndPtr) - reinterpret_cast<unsigned long>(_pStartPtr)) / sizeof(TUnit);
    }

    // -----------------------------------------------------------------------------

    template <class TOwner, class TMember>
    size_t GetMemberOffset(const TMember TOwner::* _Mtr)
    {
        return DistanceOfPtr<unsigned char>(&(static_cast<const TOwner* const>(0)->*_Mtr), static_cast<const void*>(0));
    }

    //------------------------------------------------------------------------------

    template <class TOwner, class TMember>
    TOwner& GetOwnerOfMember(TMember& _rMember, const TMember TOwner::* _Mtr)
    {
        return *SubFromPtr<TOwner*>(&_rMember, GetMemberOffset(_Mtr));
    }

    //------------------------------------------------------------------------------

    template <class TOwner, class TMember>
    const TOwner& GetOwnerOfMember(const TMember& _rMember, const TMember TOwner::* _Mtr)
    {
        return *SubFromPtr<const TOwner*>(&_rMember, GetMemberOffset(_Mtr));
    }
} // namespace MEM

namespace
{
    template <int TNumberOfBytesPerChunk>
    class CAllocator
    {
        public:

            static const int s_NumberOfBytesPerChunk = TNumberOfBytesPerChunk;

        public:

            typedef CAllocator<TNumberOfBytesPerChunk> CThis;

        public:

            CAllocator(int _NumberOfChunksPerPage)
                : m_NumberOfChunksPerPage(_NumberOfChunksPerPage)
                , m_NumberOfBytesPerPage (sizeof(SPage) + _NumberOfChunksPerPage * s_NumberOfBytesPerChunk)
                , m_pFirstPage           (0)
                , m_pFirstFreeChunk      (0)
            {
                assert(_NumberOfChunksPerPage != 0);
            }

           ~CAllocator()
            {
                Clear();
            }

        public:

            void* AllocateMemory()
            {
                SChunk* pChunk;
                SChunk* pFirstChunk;
                SPage*  pPage;

                if (m_pFirstFreeChunk == 0)
                {
                    // -----------------------------------------------------------------------------
                    // Allocate a new page and add it to the list of pages.
                    // -----------------------------------------------------------------------------
                    pPage = static_cast<SPage*>(::malloc(m_NumberOfBytesPerPage));

                    if (pPage == 0)
                    {
                        //throw std::bad_alloc("Failed to allocate resource memory.");
                    }

                    pPage->m_pNextPage = m_pFirstPage; m_pFirstPage = pPage;

                    // -----------------------------------------------------------------------------
                    // Add the chunks of the new page into the free list. Insert those free chunks 
                    // in reverse order, so when we pop the chunks from the free list they are in
                    // increasing order.
                    // -----------------------------------------------------------------------------
                    pFirstChunk = GetFirstChunkOfPage(pPage);
                    pChunk      = pFirstChunk + m_NumberOfChunksPerPage;

                    while (pChunk != pFirstChunk)
                    {
                        PushFreeChunkToFront(-- pChunk);
                    }
                }

                pChunk = PopFreeChunkFromFront();

                return pChunk;
            }

            void FreeMemory(void* _pChunk)
            {
                SChunk* pChunk;

                assert(_pChunk != 0);

                pChunk = static_cast<SChunk*>(_pChunk);

                PushFreeChunkToFront(pChunk);
            }

            void Clear()
            {
                SPage* pPage;

                while (m_pFirstPage != 0)
                {
                    pPage = m_pFirstPage;

                    m_pFirstPage = m_pFirstPage->m_pNextPage;

                    ::free(pPage);
                }

                m_pFirstFreeChunk = 0;
            }

        private:

            static_assert(TNumberOfBytesPerChunk > 0, "Number of bytes per chunk has to be greater 0.");

        private:

            struct SChunk
            {
                union
                {
                    unsigned char m_Chunk[TNumberOfBytesPerChunk];
                    SChunk*       m_pNextFreeChunk;
                };
            };

        private:

            struct SPage
            {
                SPage* m_pNextPage;
            };

        private:

            const int m_NumberOfChunksPerPage;
            const int m_NumberOfBytesPerPage;
            SPage*    m_pFirstPage;
            SChunk*   m_pFirstFreeChunk;

        private:

            bool HasFreeChunk() const
            {
                return m_pFirstFreeChunk != 0;
            }

            void PushFreeChunkToFront(SChunk* _pChunk)
            {
                assert(_pChunk != 0);

                _pChunk->m_pNextFreeChunk = m_pFirstFreeChunk;

                m_pFirstFreeChunk = _pChunk;
            }

            SChunk* PopFreeChunkFromFront()
            {
                SChunk* pChunk;

                assert(HasFreeChunk());

                pChunk = m_pFirstFreeChunk;

                m_pFirstFreeChunk = m_pFirstFreeChunk->m_pNextFreeChunk;

                return pChunk;
            }

            SChunk* GetFirstChunkOfPage(SPage* _pPage)
            {
                assert(_pPage != 0);

                return reinterpret_cast<SChunk*>(_pPage + 1);
            }

        private:

            CAllocator(const CThis&);

            CThis& operator = (const CThis&);
    };
} // namespace MEM

namespace
{
    template <class T>
    class CSmartPtr
    {
        public:

            typedef CSmartPtr<T> CThis;
            typedef T            X;
            typedef T*           XPtr;
            typedef const T*     XConstPtr;
            typedef T&           XRef;
            typedef const T&     XConstRef;

        public:

            CSmartPtr()
                : m_pObject(0)
            {
            }

            explicit CSmartPtr(XPtr _pObject)
                : m_pObject(_pObject)
            {
                AddRef(_pObject);
            }

            CSmartPtr(const CThis& _rPtr)
                : m_pObject(_rPtr.m_pObject)
            {
                AddRef(m_pObject);
            }

           ~CSmartPtr()
            {
                Release(m_pObject);
            }

        public:

            CThis& operator = (const CThis& _rPtr)
            {
                XPtr pObject;
                
                pObject = m_pObject; m_pObject = _rPtr.m_pObject;

                AddRef(m_pObject); Release(pObject);

                return *this;
            }

            CThis& operator = (XPtr _pObject)
            {
                XPtr pObject;
                
                pObject = m_pObject; m_pObject = _pObject;

                AddRef(m_pObject); Release(pObject);

                return *this;
            }

        public:

            bool operator < (XConstPtr _pObject) const 
            { 
                return m_pObject < _pObject;
            }

            bool operator <= (XConstPtr _pObject) const 
            { 
                return m_pObject <= _pObject;
            }

            bool operator > (XConstPtr _pObject) const 
            { 
                return m_pObject > _pObject;
            }

            bool operator >= (XConstPtr _pObject) const 
            { 
                return m_pObject >= _pObject;
            }

            bool operator == (XConstPtr _pObject) const 
            { 
                return m_pObject == _pObject;
            }

            bool operator != (XConstPtr _pObject) const 
            { 
                return m_pObject != _pObject;
            }

        public:

            bool operator < (const CThis& _rPtr) const 
            { 
                return m_pObject < _rPtr.m_pObject;
            }

            bool operator <= (const CThis& _rPtr) const 
            { 
                return m_pObject <= _rPtr.m_pObject;
            }

            bool operator > (const CThis& _rPtr) const 
            { 
                return m_pObject > _rPtr.m_pObject;
            }

            bool operator >= (const CThis& _rPtr) const 
            { 
                return m_pObject >= _rPtr.m_pObject;
            }

            bool operator == (const CThis& _rPtr) const 
            { 
                return m_pObject == _rPtr.m_pObject;
            }

            bool operator != (const CThis& _rPtr) const 
            { 
                return m_pObject != _rPtr.m_pObject;
            }

        public:

            XRef operator * ()
            { 
                assert(IsValid());

                return *m_pObject;
            }

            XConstRef operator * () const
            { 
                assert(IsValid());

                return *m_pObject;
            }

            XPtr operator -> ()
            { 
                return m_pObject;
            }

            XConstPtr operator -> () const 
            { 
                return m_pObject;
            }

        public:

            bool IsValid() const 
            { 
                return m_pObject != 0;
            }

        public:

            XPtr GetPtr()
            { 
                return m_pObject;
            }

            XConstPtr GetPtr() const
            { 
                return m_pObject;
            }

        public:

            int AddRef()
            { 
                return AddRef(m_pObject);
            }

            int Release() 
            { 
                return Release(m_pObject);
            }

        private:

            XPtr  m_pObject;

        private:

            static int AddRef(XPtr _pObject)
            { 
                return (_pObject != 0) ? _pObject->AddRef() : 0;
            }

            static int Release(XPtr _pObject) 
            { 
                return (_pObject != 0) ? _pObject->Release() : 0;
            }
    };
} // namespace

namespace
{
    class CSmartPointee
    {
        public:

            CSmartPointee()
                : m_NumberOfReferences(0)
            {
            }

           ~CSmartPointee()
            {
                assert(m_NumberOfReferences == 0);
            }

        public:

            int AddRef()
            {
                return ++ m_NumberOfReferences;
            }

            int Release()
            {
                assert(m_NumberOfReferences > 0);

                return -- m_NumberOfReferences;
            }

        private:

            int m_NumberOfReferences;

        private:

            CSmartPointee(const CSmartPointee&);

            CSmartPointee& operator = (const CSmartPointee&);
    };
} // namespace

namespace
{
    class CVertexShader : public CSmartPointee
    {
        public:

            ID3D10VertexShader* m_pNativeVertexShader;
            ID3D10Blob*         m_pNativeVertexShaderBlob;

        protected:

            CVertexShader()
                : CSmartPointee            ()
                , m_pNativeVertexShader    (0)
                , m_pNativeVertexShaderBlob(0)
            {
            }

           ~CVertexShader()
            {
                SAFE_RELEASE(m_pNativeVertexShader    );
                SAFE_RELEASE(m_pNativeVertexShaderBlob);
            }

        private:

            CVertexShader(const CVertexShader&);

            CVertexShader& operator = (const CVertexShader&);
    };
} // namespace

namespace
{
    class CPixelShader : public CSmartPointee
    {
        public:

            ID3D10PixelShader* m_pNativePixelShader;
            ID3D10Blob*        m_pNativePixelShaderBlob;

        protected:

            CPixelShader()
                : CSmartPointee           ()
                , m_pNativePixelShader    (0)
                , m_pNativePixelShaderBlob(0)
            {
            }

           ~CPixelShader()
            {
                SAFE_RELEASE(m_pNativePixelShader    );
                SAFE_RELEASE(m_pNativePixelShaderBlob);
            }

        private:

            CPixelShader(const CPixelShader&);

            CPixelShader& operator = (const CPixelShader&);
    };
} // namespace

namespace
{
    class CInputLayout : public CSmartPointee
    {
        public:

            ID3D10InputLayout* m_pNativeInputLayout;

        protected:

            CInputLayout()
                : CSmartPointee       ()
                , m_pNativeInputLayout(0)
            {
            }

           ~CInputLayout()
            {
                SAFE_RELEASE(m_pNativeInputLayout);
            }

        private:

            CInputLayout(const CInputLayout&);

            CInputLayout& operator = (const CInputLayout&);
    };
} // namespace

namespace
{
    class CTexture2D : public CSmartPointee
    {
        public:

            int GetWidth() const
            {
                assert(m_pNativeTexture != 0);

                D3D10_TEXTURE2D_DESC TextureDiscriptor;

                m_pNativeTexture->GetDesc(&TextureDiscriptor);

                return TextureDiscriptor.Width;
            }

            int GetHeight() const
            {
                assert(m_pNativeTexture != 0);

                D3D10_TEXTURE2D_DESC TextureDiscriptor;

                m_pNativeTexture->GetDesc(&TextureDiscriptor);

                return TextureDiscriptor.Height;
            }

        public:

            ID3D10Texture2D*          m_pNativeTexture;
            ID3D10ShaderResourceView* m_pNativeTextureView;

        protected:

            CTexture2D()
                : CSmartPointee       ()
                , m_pNativeTexture    (0)
                , m_pNativeTextureView(0)
            {
            }

           ~CTexture2D()
            {
                SAFE_RELEASE(m_pNativeTexture    );
                SAFE_RELEASE(m_pNativeTextureView);
            }

        private:

            CTexture2D(const CTexture2D&);

            CTexture2D& operator = (const CTexture2D&);
    };
} // namespace

namespace
{
    class CMesh : public CSmartPointee
    {
        public:

            int                      m_NumberOfVertices;
            int                      m_NumberOfBytesPerVertex;
            void*                    m_pVertices;
            int                      m_NumberOfIndices;
            int*                     m_pIndices;
            CSmartPtr<CVertexShader> m_VertexShaderPtr;
            CSmartPtr<CPixelShader>  m_PixelShaderPtr;
            CSmartPtr<CInputLayout>  m_InputLayoutPtr;
            CSmartPtr<CTexture2D>    m_TexturePtr;
            ID3D10Buffer*            m_pNativeVertexBuffer;
            ID3D10Buffer*            m_pNativeIndexBuffer;

        protected:

            CMesh::CMesh()
                : m_NumberOfVertices      (0)
                , m_NumberOfBytesPerVertex(0)
                , m_pVertices             (0)
                , m_NumberOfIndices       (0)
                , m_pIndices              (0)
                , m_VertexShaderPtr       (0)
                , m_PixelShaderPtr        (0)
                , m_InputLayoutPtr        (0)
                , m_TexturePtr            (0)
                , m_pNativeVertexBuffer   (0)
                , m_pNativeIndexBuffer    (0)
            {
            }

            CMesh::~CMesh()
            {
                if (m_pVertices != 0) delete[] m_pVertices;
                if (m_pIndices  != 0) delete[] m_pIndices;

                SAFE_RELEASE(m_pNativeVertexBuffer);
                SAFE_RELEASE(m_pNativeIndexBuffer );
            }

        private:

            CMesh(const CMesh&);

            CMesh& operator = (const CMesh&);
    };
} // namespace

namespace
{
    class CObject : public CSmartPointee
    {
        public:

            CSmartPtr<CMesh> m_MeshPtr;
            D3DXMATRIX       m_WorldMatrix;

        protected:

            CObject::CObject()
                : m_MeshPtr    (0)
                , m_WorldMatrix()
            {
            }

            CObject::~CObject()
            {
            }

        private:

            CObject(const CObject&);

            CObject& operator = (const CObject&);
    };
} // namespace

namespace
{
    class CYoshiX
    {
        public:

            static CYoshiX& GetInstance();

        public:

            bool OpenWindow(int _Width, int _Height, const char* _pTitle);
            bool CloseWindow();

            bool StartupDirectX();
            bool ShutdownDirectX();

            bool RunApplication(IApplication* _pApplication);

            bool SetDepthTest(bool _Flag);
            bool SetWireFrame(bool _Flag);

            void SetClearColor(const float* _pColor);

        public:

            bool CreateTexture(const char* _pPath, BHandle* _ppTexture);
            bool ReleaseTexture(BHandle _pTexture);

        public:

            bool CreateMesh(const float* _pVertices, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh);
            bool CreateMesh(const float* _pVertices, const float* _pNormals, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh);
            bool CreateColoredMesh(const float* _pVertices, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh);
            bool CreateColoredMesh(const float* _pVertices, const float* _pNormals, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh);
            bool CreateTexturedMesh(const float* _pVertices, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh);
            bool CreateTexturedMesh(const float* _pVertices, const float* _pNormals, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh);
            bool ReleaseMesh(BHandle _pMesh);

        public:

            bool CreateObject(BHandle _pMesh, BHandle* _ppObject);
            bool ReleaseObject(BHandle _pObject);

        public:

            bool DrawObject(BHandle _pObject);

        public:

            void SetWorldMatrix(BHandle _pObject, const float* _pMatrix);
            void SetViewMatrix(const float* _pMatrix);
            void SetProjectionMatrix(const float* _pMatrix);

        public:

            void SetLightPosition(const float* _pPosition);
            void SetLightColor(const float* _pAmbientColor, const float* _pDiffuseColor, const float* _pSpecularColor, float _SpecularExponent);

        private:

            enum EMaterial
            {
                Default,
                DefaultIlluminated,
                Color,
                ColorIlluminated,
                Texture,
                TextureIlluminated,
                NumberOfMaterials,
            };

        private:

            struct SLink
            {
                SLink* m_pNext;
                SLink* m_pPrevious;
            };

        private:

            template <class T> 
            class CConstIterator
            {
                friend class CYoshiX;

                public:

                    typedef CConstIterator<T> CThis;
                    typedef T                 X;
                    typedef const X*          XPtr;
                    typedef const X&          XRef;

                public:

                    CConstIterator()
                        : m_pLink(0)
                    {
                    }

                    CConstIterator(const CThis& _rIterator)
                        : m_pLink(_rIterator.m_pLink)
                    {
                    }

                public:

                    CThis& operator = (const CThis& _rIterator)
                    {
                        m_pLink = _rIterator.m_pLink;

                        return *this;
                    }

                public:

                    XRef operator * () const
                    {
                        assert(m_pLink != 0);

                        return GetOwner(*m_pLink, X::m_Link);
                    }

                    XPtr operator -> () const
                    {
                        assert(m_pLink != 0);

                        return &GetOwner(*m_pLink, X::m_Link);
                    }

                public:

                    CThis& operator ++ ()
                    {
                        m_pLink = m_pLink->m_pNext;

                        return *this;
                    }

                    CThis& operator -- ()
                    {
                        m_pLink = m_pLink->m_pPrevious;

                        return *this;
                    }

                    CThis operator ++ (int)
                    {
                        CThis Iterator(m_pLink);

                        ++ (*this);

                        return Iterator;
                    }

                    CThis operator -- (int)
                    {
                        CThis Iterator(m_pLink);

                        -- (*this);

                        return Iterator;
                    }

                public:

                    bool operator == (const CThis& _rIterator) const
                    {
                        return m_pLink == _rIterator.m_pLink;
                    }

                    bool operator != (const CThis& _rIterator) const
                    {
                        return m_pLink != _rIterator.m_pLink;
                    }

                protected:

                    SLink* m_pLink;

                protected:

                    explicit CConstIterator(SLink* _pLink)
                        : m_pLink(_pLink)
                    {
                    }
            };

        private:

            template <class T> 
            class CIterator : public CConstIterator<T>
            {
                friend class CYoshiX;

                public:

                    typedef CIterator<T>      CThis;
                    typedef CConstIterator<T> CBase;
                    typedef const X*          XPtr;
                    typedef const X&          XRef;

                public:

                    CIterator()
                        : CBase()
                    {
                    }

                    CIterator(const CThis& _rIterator)
                        : CBase(_rIterator.m_pLink)
                    {
                    }

                public:

                    CThis& operator = (const CThis& _rIterator)
                    {
                        m_pLink = _rIterator.m_pLink;

                        return *this;
                    }

                public:

                    XRef operator * () const
                    {
                        assert(m_pLink != 0);

                        return GetOwner(*m_pLink, X::m_Link);
                    }

                    XPtr operator -> () const
                    {
                        assert(m_pLink != 0);

                        return &GetOwner(*m_pLink, X::m_Link);
                    }

                public:

                    CThis& operator ++ ()
                    {
                        m_pLink = m_pLink->m_pNext;

                        return *this;
                    }

                    CThis& operator -- ()
                    {
                        m_pLink = m_pLink->m_pPrevious;

                        return *this;
                    }

                    CThis operator ++ (int)
                    {
                        CThis Iterator(m_pLink);

                        ++ (*this);

                        return Iterator;
                    }

                    CThis operator -- (int)
                    {
                        CThis Iterator(m_pLink);

                        -- (*this);

                        return Iterator;
                    }

                private:

                    explicit CIterator(SLink* _pLink)
                        : CBase(_pLink)
                    {
                    }
            };

        private:

            class CInternVertexShader : public CVertexShader
            {
                friend class CYoshiX;

                private:

                    SLink m_Link;
            };

            class CInternPixelShader : public CPixelShader
            {
                friend class CYoshiX;

                private:

                    SLink m_Link;
            };

            class CInternInputLayout : public CInputLayout
            {
                friend class CYoshiX;

                private:

                    SLink m_Link;
            };

            class CInternTexture2D : public CTexture2D
            {
                friend class CYoshiX;

                private:

                    SLink m_Link;
            };

            class CInternMesh : public CMesh
            {
                friend class CYoshiX;

                private:

                    SLink m_Link;
            };

            class CInternObject : public CObject
            {
                friend class CYoshiX;

                private:

                    SLink m_Link;
            };

        private:

            typedef CAllocator<sizeof(CInternVertexShader)> CVertexShaderAllocator;
            typedef CAllocator<sizeof(CInternPixelShader )> CPixelShaderAllocator;
            typedef CAllocator<sizeof(CInternInputLayout )> CInputLayoutAllocator;
            typedef CAllocator<sizeof(CInternTexture2D   )> CTexture2DAllocator;
            typedef CAllocator<sizeof(CInternMesh        )> CMeshAllocator;
            typedef CAllocator<sizeof(CInternObject      )> CObjectAllocator;

        private:

            typedef CIterator     <CInternVertexShader> CVertexShaderIterator;
            typedef CConstIterator<CInternVertexShader> CConstVertexShaderIterator;
            typedef CIterator     <CInternPixelShader > CPixelShaderIterator;
            typedef CConstIterator<CInternPixelShader > CConstPixelShaderIterator;
            typedef CIterator     <CInternInputLayout > CInputLayoutIterator;
            typedef CConstIterator<CInternInputLayout > CConstInputLayoutIterator;
            typedef CIterator     <CInternTexture2D   > CTexture2DIterator;
            typedef CConstIterator<CInternTexture2D   > CConstTexture2DIterator;
            typedef CIterator     <CInternMesh        > CMeshIterator;
            typedef CConstIterator<CInternMesh        > CConstMeshIterator;
            typedef CIterator     <CInternObject      > CObjectIterator;
            typedef CConstIterator<CInternObject      > CConstObjectIterator;

        private:

            static const int s_NumberOfMaterials       = NumberOfMaterials;
            static const int s_NumberOfElementsPerPage = 256;

        private:

            static const wchar_t* s_pWindowClassName;                           ///< Identifier of the windows descriptor.

        private:

            int                      m_Width;                                   ///< The width of the render area in pixels.
            int                      m_Height;                                  ///< The height of the render area in pixels.
            float                    m_ClearColor[4];
            CVertexShaderAllocator   m_VertexShaderAllocator;
            CPixelShaderAllocator    m_PixelShaderAllocator;
            CInputLayoutAllocator    m_InputLayoutAllocator;
            CTexture2DAllocator      m_Texture2DAllocator;
            CMeshAllocator           m_MeshAllocator;
            CObjectAllocator         m_ObjectAllocator;
            SLink                    m_VertexShader;
            SLink                    m_PixelShader;
            SLink                    m_InputLayouts;
            SLink                    m_Textures2D;
            SLink                    m_Meshes;
            SLink                    m_Objects;
            CInternVertexShader*     m_pVertexShader[s_NumberOfMaterials];
            CInternPixelShader*      m_pPixelShader [s_NumberOfMaterials];
            CInternInputLayout*      m_pInputLayouts[s_NumberOfMaterials];
            SLight                   m_Light;
            D3DXMATRIX               m_WorldMatrix;
            D3DXMATRIX               m_ViewMatrix;
            D3DXMATRIX               m_ProjectionMatrix;
            IApplication*            m_pApplication;
            HINSTANCE                m_pNativeApplication;                      ///< Operating system handle to our application.
            HWND                     m_pNativeWindow;                           ///< A handle of the operating system to the window.
            ID3D10Device*            m_pNativeDevice;                           ///< The root of all evil: The DirectX device.
            IDXGIFactory*            m_pNativeFactory;                          ///< Factory used to create the swap chain.
            IDXGISwapChain*          m_pNativeSwapChain;                        ///< An interface which allows double buffering.
            ID3D10Texture2D*         m_pNativeColorBuffer;                      ///< The color buffer, in which the scene is rendered by the GPU.
            ID3D10RenderTargetView*  m_pNativeColorBufferView;                  ///< Defines to interpret the color buffer as a render target.
            ID3D10Texture2D*         m_pNativeDepthBuffer;                      ///< The depth buffer, in which the depth information of the scene is rendered by the GPU.
            ID3D10DepthStencilView*  m_pNativeDepthBufferView;                  ///< Defines to interpret the depth buffer as a render target.
            ID3D10RasterizerState*   m_pNativeSolidRasterizerState;             ///< Rasterizer state to render objects with filled polygons.
            ID3D10RasterizerState*   m_pNativeWireFrameRasterizerState;         ///< Rasterizer state to render objects as wireframes.
            ID3D10DepthStencilState* m_pNativeDepthOnDepthStencilState;         ///< Depth stencil state with activated depth test.
            ID3D10DepthStencilState* m_pNativeDepthOffDepthStencilState;        ///< Depth stencil state with deactivated depth test.
            ID3D10SamplerState*      m_pNativeSamplerState;
            ID3D10Buffer*            m_pNativePerFrameVSBuffer;                 ///< Vertex shader constant buffer, which is modified only once per frame.
            ID3D10Buffer*            m_pNativePerFramePSBuffer;                 ///< Pixel shader constant buffer, which is modified only once per frame.
            ID3D10Buffer*            m_pNativePerDrawCallVSBuffer;              ///< Vertex shader constant buffer, which is modified per draw call.

        private:

            static long __stdcall ProcessMessages(HWND _NativeWindowHandle, unsigned int _MessageType, unsigned int _Arg1, long _Arg2);

        private:

            CYoshiX();
           ~CYoshiX();

        private:

            void Clear();

        private:

            void BeginFrame();
            void EndFrame();

        private:

            bool OnResizeWindow();

        private:

            bool SetViewPort(int _Width, int _Height);

        private:

            CVertexShaderIterator BeginVertexShader()
            {
                return ++ EndVertexShader();
            }

            CConstVertexShaderIterator BeginVertexShader() const
            {
                return ++ EndVertexShader();
            }

            CVertexShaderIterator EndVertexShader()
            {
                return CVertexShaderIterator(&m_VertexShader);
            }

            CConstVertexShaderIterator EndVertexShader() const
            {
                return CConstVertexShaderIterator(const_cast<SLink*>(&m_VertexShader));
            }

        private:

            CPixelShaderIterator BeginPixelShader()
            {
                return ++ EndPixelShader();
            }

            CConstPixelShaderIterator BeginPixelShader() const
            {
                return ++ EndPixelShader();
            }

            CPixelShaderIterator EndPixelShader()
            {
                return CPixelShaderIterator(&m_PixelShader);
            }

            CConstPixelShaderIterator EndPixelShader() const
            {
                return CConstPixelShaderIterator(const_cast<SLink*>(&m_PixelShader));
            }

        private:

            CInputLayoutIterator BeginInputLayout()
            {
                return ++ EndInputLayout();
            }

            CConstInputLayoutIterator BeginInputLayout() const
            {
                return ++ EndInputLayout();
            }

            CInputLayoutIterator EndInputLayout()
            {
                return CInputLayoutIterator(&m_InputLayouts);
            }

            CConstInputLayoutIterator EndInputLayout() const
            {
                return CConstInputLayoutIterator(const_cast<SLink*>(&m_InputLayouts));
            }

        private:

            CTexture2DIterator BeginTexture2D()
            {
                return ++ EndTexture2D();
            }

            CConstTexture2DIterator BeginTexture2D() const
            {
                return ++ EndTexture2D();
            }

            CTexture2DIterator EndTexture2D()
            {
                return CTexture2DIterator(&m_Textures2D);
            }

            CConstTexture2DIterator EndTexture2D() const
            {
                return CConstTexture2DIterator(const_cast<SLink*>(&m_Textures2D));
            }

        private:

            CMeshIterator BeginMesh()
            {
                return ++ EndMesh();
            }

            CConstMeshIterator BeginMesh() const
            {
                return ++ EndMesh();
            }

            CMeshIterator EndMesh()
            {
                return CMeshIterator(&m_Meshes);
            }

            CConstMeshIterator EndMesh() const
            {
                return CConstMeshIterator(const_cast<SLink*>(&m_Meshes));
            }

        private:

            CObjectIterator BeginObject()
            {
                return ++ EndObject();
            }

            CConstObjectIterator BeginObject() const
            {
                return ++ EndObject();
            }

            CObjectIterator EndObject()
            {
                return CObjectIterator(&m_Objects);
            }

            CConstObjectIterator EndObject() const
            {
                return CConstObjectIterator(const_cast<SLink*>(&m_Objects));
            }

        private:

            CInternVertexShader* AllocateVertexShader()
            {
                return AllocateResource<CInternVertexShader>(m_VertexShaderAllocator);
            }

            void FreeVertexShader(CInternVertexShader* _pResource)
            {
                return FreeResource<CInternVertexShader>(m_VertexShaderAllocator, _pResource);
            }

        private:

            CInternPixelShader* AllocatePixelShader()
            {
                return AllocateResource<CInternPixelShader>(m_PixelShaderAllocator);
            }

            void FreePixelShader(CInternPixelShader* _pResource)
            {
                return FreeResource<CInternPixelShader>(m_PixelShaderAllocator, _pResource);
            }

        private:

            CInternInputLayout* AllocateInputLayout()
            {
                return AllocateResource<CInternInputLayout>(m_InputLayoutAllocator);
            }

            void FreeInputLayout(CInternInputLayout* _pResource)
            {
                return FreeResource<CInternInputLayout>(m_InputLayoutAllocator, _pResource);
            }

        private:

            CInternTexture2D* AllocateTexture2D()
            {
                return AllocateResource<CInternTexture2D>(m_Texture2DAllocator);
            }

            void FreeTexture2D(CInternTexture2D* _pResource)
            {
                return FreeResource<CInternTexture2D>(m_Texture2DAllocator, _pResource);
            }

        private:

            CInternMesh* AllocateMesh()
            {
                return AllocateResource<CInternMesh>(m_MeshAllocator);
            }

            void FreeMesh(CInternMesh* _pResource)
            {
                return FreeResource<CInternMesh>(m_MeshAllocator, _pResource);
            }

        private:

            CInternObject* AllocateObject()
            {
                return AllocateResource<CInternObject>(m_ObjectAllocator);
            }

            void FreeObject(CInternObject* _pResource)
            {
                return FreeResource<CInternObject>(m_ObjectAllocator, _pResource);
            }

        private:

            template <class T, class TAllocator>
            T* AllocateResource(TAllocator& _rAllocator)
            {
                T* pResource;

                pResource = reinterpret_cast<T*>(_rAllocator.AllocateMemory());

                new (pResource) T();

                pResource->m_Link.m_pNext           = &m_VertexShader;
                pResource->m_Link.m_pPrevious       =  m_VertexShader.m_pPrevious;

                m_VertexShader.m_pPrevious->m_pNext = &pResource->m_Link;
                m_VertexShader.m_pPrevious          = &pResource->m_Link;

                return pResource;
            }

            template <class T, class TAllocator>
            void FreeResource(TAllocator& _rAllocator, T* _pResource)
            {
                assert(_pResource != 0);

                _pResource->m_Link.m_pPrevious->m_pNext     = _pResource->m_Link.m_pNext;
                _pResource->m_Link.m_pNext    ->m_pPrevious = _pResource->m_Link.m_pPrevious;

                _pResource->m_Link.m_pNext                  = &_pResource->m_Link;
                _pResource->m_Link.m_pPrevious              = &_pResource->m_Link;

                _pResource->~T();

                _rAllocator.FreeMemory(_pResource);
            }

        private:

            template <class T>
            T& GetOwner(SLink& _rLink, SLink T::* _LinkMtr) const
            {
                return GetOwnerOfMember<T, SLink>(_rLink, _LinkMtr);
            }

            void Clear(SLink& _rLink) const
            {
                _rLink.m_pNext     = &_rLink;
                _rLink.m_pPrevious = &_rLink;
            }

            bool IsEmpty(const SLink& _rLink) const
            {
                return (_rLink.m_pNext == &_rLink);
            }

        private:

            CYoshiX(const CYoshiX&);

            CYoshiX& operator = (const CYoshiX&);
    };
} // namespace

namespace
{
    const wchar_t* CYoshiX::s_pWindowClassName = L"ApplicationWindow";
} // namespace

namespace
{
    CYoshiX& CYoshiX::GetInstance()
    {
        static CYoshiX s_Singleton;

        return s_Singleton;
    }

    // -----------------------------------------------------------------------------

    CYoshiX::CYoshiX()
        : m_Width                           (-1)
        , m_Height                          (-1)
        , m_VertexShaderAllocator           (s_NumberOfElementsPerPage)
        , m_PixelShaderAllocator            (s_NumberOfElementsPerPage)
        , m_InputLayoutAllocator            (s_NumberOfElementsPerPage)
        , m_Texture2DAllocator              (s_NumberOfElementsPerPage)
        , m_MeshAllocator                   (s_NumberOfElementsPerPage)
        , m_ObjectAllocator                 (s_NumberOfElementsPerPage)
        , m_VertexShader                    ()
        , m_PixelShader                     ()
        , m_InputLayouts                    ()
        , m_Textures2D                      ()
        , m_Meshes                          ()
        , m_Objects                         ()
        , m_Light                           ()
        , m_WorldMatrix                     ()
        , m_ViewMatrix                      ()
        , m_ProjectionMatrix                ()
        , m_pApplication                    (0)
        , m_pNativeApplication              (0)
        , m_pNativeWindow                   (0)
        , m_pNativeDevice                   (0)
        , m_pNativeFactory                  (0)
        , m_pNativeSwapChain                (0)
        , m_pNativeColorBuffer              (0)
        , m_pNativeDepthBuffer              (0)
        , m_pNativeColorBufferView          (0)
        , m_pNativeDepthBufferView          (0)
        , m_pNativeSolidRasterizerState     (0)
        , m_pNativeWireFrameRasterizerState (0)     
        , m_pNativeDepthOnDepthStencilState (0)     
        , m_pNativeDepthOffDepthStencilState(0)
        , m_pNativeSamplerState             (0)
        , m_pNativePerFrameVSBuffer         (0)
        , m_pNativePerFramePSBuffer         (0)
        , m_pNativePerDrawCallVSBuffer      (0)
    {
        ::memset(m_ClearColor, 0, sizeof(m_ClearColor));

        Clear(m_VertexShader);
        Clear(m_PixelShader );
        Clear(m_InputLayouts);
        Clear(m_Textures2D  );
        Clear(m_Meshes      );

        ::memset(m_pVertexShader, 0, sizeof(m_pVertexShader));
        ::memset(m_pPixelShader , 0, sizeof(m_pPixelShader ));
        ::memset(m_pInputLayouts, 0, sizeof(m_pInputLayouts));

        ::memset(&m_Light, 0, sizeof(m_Light));
    }

    // -----------------------------------------------------------------------------

    CYoshiX::~CYoshiX()
    {
        assert(IsEmpty(m_VertexShader));
        assert(IsEmpty(m_PixelShader ));
        assert(IsEmpty(m_InputLayouts));
        assert(IsEmpty(m_Textures2D  ));
        assert(IsEmpty(m_Meshes      ));
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::OpenWindow(int _Width, int _Height, const char* _pTitle)
    {
        HWND      pNativeWindow;
        HINSTANCE pNativeApplication;
        wchar_t   Title[4096];

        assert((_pTitle != 0) && (strlen(_pTitle) < (sizeof(Title) / sizeof(Title[0]))));

        pNativeApplication = ::GetModuleHandle(0);

        if (pNativeApplication == 0)
        {
            return false;
        }

        // -----------------------------------------------------------------------------
        // Define the look and feel of the window.
        // -----------------------------------------------------------------------------
        WNDCLASSEX WindowClass;

        WindowClass.cbSize        = sizeof(WindowClass);                        // The number of bytes of the 'WindowClass' descriptor.
        WindowClass.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;       // The style of our window, which for example defines the behavior when our window is resized.
        WindowClass.lpfnWndProc   = ProcessMessages;                            // The method where the messages of the operating system are processed.
        WindowClass.cbClsExtra    = 0;                                          // The number of extra bytes we want to append to our 'WindowClass' descriptor.
        WindowClass.cbWndExtra    = 0;                                          // The number of extra bytes we want to append to our 'HWND' handle.
        WindowClass.hInstance     = pNativeApplication;                         // A handle to the instance, which owns the 'ProcessMessages' method, i.e. our application.
        WindowClass.hIcon         = 0;                                          // An icon which we can associate with out window via the 'LoadIcon' method.
        WindowClass.hCursor       = LoadCursor(0, IDC_ARROW);                   // Defines the look of our cursor.
        WindowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1); // Allows us define our background behavior.
        WindowClass.lpszMenuName  = 0;                                          // Name of our menu definitions in the resources.
        WindowClass.lpszClassName = s_pWindowClassName;                         // Name of our window class, which is not the title, but an ID to get a pointer to this 'WindowClass' descriptor.
        WindowClass.hIconSm       = 0;                                          // A small icon which we can associate with out window.

        // -----------------------------------------------------------------------------
        // Registers our window class in the operating system.
        // -----------------------------------------------------------------------------
        if (!RegisterClassEx(&WindowClass))
        {
            WriteErrorMessage("Failed to register window class.");

            return false;
        }

        // -----------------------------------------------------------------------------
        // Defines the size of the window in pixels.
        // -----------------------------------------------------------------------------
        RECT Dimensions = { 0, 0, _Width, _Height };

        // -----------------------------------------------------------------------------
        // Adjust the size of the window, because we do not want, that the total window
        // including border, menu, and title has the dimensions defined by 'g_Width' and
        // 'g_Height', but the inner area where we render our scene.
        // -----------------------------------------------------------------------------
        AdjustWindowRect(&Dimensions, WS_OVERLAPPEDWINDOW, FALSE);

        int Width  = Dimensions.right  - Dimensions.left;
        int Height = Dimensions.bottom - Dimensions.top;

        // -----------------------------------------------------------------------------
        // Create the window in the operating system.
        // -----------------------------------------------------------------------------
        MultiByteToWideChar(CP_ACP, 0, _pTitle, -1, Title, sizeof(Title) / sizeof(Title[0]));

        pNativeWindow = CreateWindow(s_pWindowClassName, Title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, 0, 0, pNativeApplication, 0);

        if (pNativeWindow == 0)
        {
            UnregisterClass(s_pWindowClassName, pNativeApplication);

            WriteErrorMessage("Failed to create window.");

            return false;
        }

        m_pNativeApplication = pNativeApplication;
        m_pNativeWindow      = pNativeWindow;

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::CloseWindow()
    {
        assert(m_pNativeApplication != 0);
        assert(m_pNativeWindow      != 0);

        UnregisterClass(s_pWindowClassName, m_pNativeApplication);

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::StartupDirectX()
    {
        static const char* s_VertexShader[] =
        {
            "VSDefaultShader",
            "VSDefaultIllShader",
            "VSColShader",
            "VSColIllShader",
            "VSTexShader",
            "VSTexIllShader",
        };

        static const char* s_PixelShader[] =
        {
            "PSDefaultShader",
            "PSDefaultIllShader",
            "PSColShader",
            "PSColIllShader",
            "PSTexShader",
            "PSTexIllShader",
        };

        static const D3D10_INPUT_ELEMENT_DESC s_InputLayouts[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0,  0, D3D10_INPUT_PER_VERTEX_DATA, 0 },   // Default material
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0,  0, D3D10_INPUT_PER_VERTEX_DATA, 0 },   // Default illuminated material
            { "NORMAL"  , 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0,  0, D3D10_INPUT_PER_VERTEX_DATA, 0 },   // Color material
            { "COLOR"   , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0,  0, D3D10_INPUT_PER_VERTEX_DATA, 0 },   // Color illuminated material
            { "NORMAL"  , 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "COLOR"   , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0,  0, D3D10_INPUT_PER_VERTEX_DATA, 0 },   // Texture material
            { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT      , 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0,  0, D3D10_INPUT_PER_VERTEX_DATA, 0 },   // Texture illuminated material
            { "NORMAL"  , 0, DXGI_FORMAT_R32G32B32_FLOAT   , 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
            { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT      , 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
        };

        static const int s_NumberOfElements[] =
        {
            1,
            2,
            2,
            3,
            2,
            3,
        };

        int                      IndexOfMaterial;
        int                      IndexOfInputLayout;

        int                      NumberOfElements;

        int                      Width;
        int                      Height;
                                 
        HRESULT                  Result;
        RECT                     ViewRectangle;
                                 
        CInternVertexShader*     pVertexShader[s_NumberOfMaterials];
        CInternPixelShader*      pPixelShader [s_NumberOfMaterials];
        CInternInputLayout*      pInputLayouts[s_NumberOfMaterials];
                                 
        ID3D10Device*            pNativeDevice;
        IDXGIFactory*            pNativeFactory;
        IDXGISwapChain*          pNativeSwapChain;
        ID3D10Texture2D*         pNativeColorBuffer;
        ID3D10RenderTargetView*  pNativeColorBufferView;
        ID3D10Texture2D*         pNativeDepthBuffer;
        ID3D10DepthStencilView*  pNativeDepthBufferView;
        ID3D10RasterizerState*   pNativeSolidRasterizerState;
        ID3D10RasterizerState*   pNativeWireFrameRasterizerState;
        ID3D10DepthStencilState* pNativeDepthOnDepthStencilState;
        ID3D10DepthStencilState* pNativeDepthOffDepthStencilState;
        ID3D10SamplerState*      pNativeSamplerState;
        ID3D10Buffer*            pNativePerFrameVSBuffer;
        ID3D10Buffer*            pNativePerFramePSBuffer;
        ID3D10Buffer*            pNativePerDrawCallVSBuffer;
        ID3D10Blob*              pNativeVertexShaderBlobs[s_NumberOfMaterials];
        ID3D10VertexShader*      pNativeVertexShader     [s_NumberOfMaterials];
        ID3D10Blob*              pNativePixelShaderBlobs [s_NumberOfMaterials];
        ID3D10PixelShader*       pNativePixelShader      [s_NumberOfMaterials];
        ID3D10InputLayout*       pNativeInputLayouts     [s_NumberOfMaterials];
        ID3D10Blob*              pNativeErrorBlob;

        assert(m_pNativeApplication != 0);
        assert(m_pNativeWindow      != 0);

        // -----------------------------------------------------------------------------
        // Set the interfaces to 0 for safe release in case of an exception.
        // -----------------------------------------------------------------------------
        ::memset(pVertexShader, 0, sizeof(pVertexShader));
        ::memset(pPixelShader , 0, sizeof(pPixelShader ));
        ::memset(pInputLayouts, 0, sizeof(pInputLayouts));
                                         
        pNativeDevice                    = 0;
        pNativeFactory                   = 0;
        pNativeSwapChain                 = 0;
        pNativeColorBuffer               = 0;
        pNativeColorBufferView           = 0;
        pNativeDepthBuffer               = 0;
        pNativeDepthBufferView           = 0;
        pNativeSolidRasterizerState      = 0;
        pNativeWireFrameRasterizerState  = 0;
        pNativeDepthOnDepthStencilState  = 0;
        pNativeDepthOffDepthStencilState = 0;
        pNativeSamplerState              = 0;
        pNativePerFrameVSBuffer          = 0;
        pNativePerFramePSBuffer          = 0;
        pNativePerDrawCallVSBuffer       = 0;

        ::memset(pNativeVertexShaderBlobs, 0, sizeof(pNativeVertexShaderBlobs));
        ::memset(pNativeVertexShader     , 0, sizeof(pNativeVertexShader     ));
        ::memset(pNativePixelShaderBlobs , 0, sizeof(pNativePixelShaderBlobs ));
        ::memset(pNativePixelShader      , 0, sizeof(pNativePixelShader      ));
        ::memset(pNativeInputLayouts     , 0, sizeof(pNativeInputLayouts     ));

        try
        {
            // -----------------------------------------------------------------------------
            // Get the size of the render area.
            // -----------------------------------------------------------------------------
            ::GetClientRect(m_pNativeWindow, &ViewRectangle);

            Width  = ViewRectangle.right  - ViewRectangle.left;
            Height = ViewRectangle.bottom - ViewRectangle.top;

            // -----------------------------------------------------------------------------
            // Create the device.
            // -----------------------------------------------------------------------------
            Result = ::D3D10CreateDevice(0, D3D10_DRIVER_TYPE_HARDWARE, 0, 0, D3D10_SDK_VERSION, &pNativeDevice);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create device.");
            }

            // -----------------------------------------------------------------------------
            // Create the factory.
            // -----------------------------------------------------------------------------
            Result = ::CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pNativeFactory));

            if (Result != S_OK)
            {
                throw std::exception("Failed to create factory.");
            }

            // -----------------------------------------------------------------------------
            // Create the swap chain.
            // -----------------------------------------------------------------------------
            DXGI_SWAP_CHAIN_DESC SwapChainDescriptor;

            memset(&SwapChainDescriptor, 0, sizeof(SwapChainDescriptor));

            SwapChainDescriptor.BufferDesc.Width                   = Width;
            SwapChainDescriptor.BufferDesc.Height                  = Height;
            SwapChainDescriptor.BufferDesc.Format                  = DXGI_FORMAT_R8G8B8A8_UNORM;
            SwapChainDescriptor.BufferDesc.RefreshRate.Numerator   = 60;
            SwapChainDescriptor.BufferDesc.RefreshRate.Denominator = 1;
            SwapChainDescriptor.SampleDesc.Count                   = 1;
            SwapChainDescriptor.SampleDesc.Quality                 = 0;
            SwapChainDescriptor.BufferUsage                        = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            SwapChainDescriptor.BufferCount                        = 1;
            SwapChainDescriptor.OutputWindow                       = m_pNativeWindow;
            SwapChainDescriptor.Windowed                           = TRUE;
            SwapChainDescriptor.SwapEffect                         = DXGI_SWAP_EFFECT_SEQUENTIAL;
            SwapChainDescriptor.Flags                              = 0;

            Result = pNativeFactory->CreateSwapChain(pNativeDevice, &SwapChainDescriptor, &pNativeSwapChain);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create swap chain.");
            }

            // -----------------------------------------------------------------------------
            // Get the back buffer of the swap chain and make it to the render target, i.e.
            // to the color buffer, in which we want to render our scene.
            // -----------------------------------------------------------------------------
            Result = pNativeSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&pNativeColorBuffer));

            if (Result != S_OK)
            {
                throw std::exception("Failed to create the color buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create a view to our color buffer. A view is a class, which defines the way
            // we want to interpret the data in our buffer.
            // -----------------------------------------------------------------------------
            Result = pNativeDevice->CreateRenderTargetView(pNativeColorBuffer, 0, &pNativeColorBufferView);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create the color buffer view.");
            }

            // -----------------------------------------------------------------------------
            // Create the depth buffer.
            // -----------------------------------------------------------------------------
            D3D10_TEXTURE2D_DESC NativeDepthStencilTextureDescriptor;

            NativeDepthStencilTextureDescriptor.Width              = Width;
            NativeDepthStencilTextureDescriptor.Height             = Height;
            NativeDepthStencilTextureDescriptor.MipLevels          = 1;
            NativeDepthStencilTextureDescriptor.ArraySize          = 1;
            NativeDepthStencilTextureDescriptor.Format             = DXGI_FORMAT_D32_FLOAT;
            NativeDepthStencilTextureDescriptor.SampleDesc.Count   = 1;
            NativeDepthStencilTextureDescriptor.SampleDesc.Quality = 0;
            NativeDepthStencilTextureDescriptor.Usage              = D3D10_USAGE_DEFAULT;
            NativeDepthStencilTextureDescriptor.BindFlags          = D3D10_BIND_DEPTH_STENCIL;
            NativeDepthStencilTextureDescriptor.CPUAccessFlags     = 0;
            NativeDepthStencilTextureDescriptor.MiscFlags          = 0;

            Result = pNativeDevice->CreateTexture2D(&NativeDepthStencilTextureDescriptor, 0, &pNativeDepthBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create the depth buffer.");
            }

            D3D10_DEPTH_STENCIL_VIEW_DESC NativeDepthStencilDescriptor;

            NativeDepthStencilDescriptor.Format             = NativeDepthStencilTextureDescriptor.Format;
            NativeDepthStencilDescriptor.ViewDimension      = D3D10_DSV_DIMENSION_TEXTURE2D;
            NativeDepthStencilDescriptor.Texture2D.MipSlice = 0;

            Result = pNativeDevice->CreateDepthStencilView(pNativeDepthBuffer, &NativeDepthStencilDescriptor, &pNativeDepthBufferView);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create the depth buffer view.");
            }

            // -----------------------------------------------------------------------------
            // Create rasterizer states for solid and wire frame rendering.
            // -----------------------------------------------------------------------------
            D3D10_RASTERIZER_DESC RasterizerStateDescriptor;

            memset(&RasterizerStateDescriptor, 0, sizeof(RasterizerStateDescriptor));

            RasterizerStateDescriptor.FillMode              = D3D10_FILL_SOLID;
            RasterizerStateDescriptor.CullMode              = D3D10_CULL_BACK;
            RasterizerStateDescriptor.FrontCounterClockwise = true;
            RasterizerStateDescriptor.DepthBias             = 0;
            RasterizerStateDescriptor.DepthBiasClamp        = 0;
            RasterizerStateDescriptor.SlopeScaledDepthBias  = 0;
            RasterizerStateDescriptor.ScissorEnable         = false;
            RasterizerStateDescriptor.MultisampleEnable     = false;
            RasterizerStateDescriptor.AntialiasedLineEnable = false;

            Result = pNativeDevice->CreateRasterizerState(&RasterizerStateDescriptor, &pNativeSolidRasterizerState);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create rasterizer state.");
            }

            memset(&RasterizerStateDescriptor, 0, sizeof(RasterizerStateDescriptor));

            RasterizerStateDescriptor.FillMode              = D3D10_FILL_WIREFRAME;
            RasterizerStateDescriptor.CullMode              = D3D10_CULL_BACK;
            RasterizerStateDescriptor.FrontCounterClockwise = true;
            RasterizerStateDescriptor.DepthBias             = 0;
            RasterizerStateDescriptor.DepthBiasClamp        = 0;
            RasterizerStateDescriptor.SlopeScaledDepthBias  = 0;
            RasterizerStateDescriptor.ScissorEnable         = false;
            RasterizerStateDescriptor.MultisampleEnable     = false;
            RasterizerStateDescriptor.AntialiasedLineEnable = false;

            Result = pNativeDevice->CreateRasterizerState(&RasterizerStateDescriptor, &pNativeWireFrameRasterizerState);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create rasterizer state.");
            }

            // -----------------------------------------------------------------------------
            // Create depth stencil states for enabled and disabled depth test rendering.
            // -----------------------------------------------------------------------------
            D3D10_DEPTH_STENCIL_DESC DepthStencilStateDescriptor;

            memset(&DepthStencilStateDescriptor, 0, sizeof(DepthStencilStateDescriptor));

            DepthStencilStateDescriptor.DepthEnable                  = true;
            DepthStencilStateDescriptor.DepthWriteMask               = D3D10_DEPTH_WRITE_MASK_ALL;
            DepthStencilStateDescriptor.DepthFunc                    = D3D10_COMPARISON_LESS;
            DepthStencilStateDescriptor.StencilEnable                = false;
            DepthStencilStateDescriptor.StencilReadMask              = D3D10_DEFAULT_STENCIL_READ_MASK;
            DepthStencilStateDescriptor.StencilWriteMask             = D3D10_DEFAULT_STENCIL_WRITE_MASK;
            DepthStencilStateDescriptor.FrontFace.StencilFailOp      = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.FrontFace.StencilPassOp      = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.FrontFace.StencilFunc        = D3D10_COMPARISON_ALWAYS;
            DepthStencilStateDescriptor.BackFace .StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.BackFace .StencilPassOp      = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.BackFace .StencilFunc        = D3D10_COMPARISON_ALWAYS;

            Result = pNativeDevice->CreateDepthStencilState(&DepthStencilStateDescriptor, &pNativeDepthOnDepthStencilState);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create depth stencil state.");
            }

            memset(&DepthStencilStateDescriptor, 0, sizeof(DepthStencilStateDescriptor));

            DepthStencilStateDescriptor.DepthEnable                  = false;
            DepthStencilStateDescriptor.DepthWriteMask               = D3D10_DEPTH_WRITE_MASK_ALL;
            DepthStencilStateDescriptor.DepthFunc                    = D3D10_COMPARISON_LESS;
            DepthStencilStateDescriptor.StencilEnable                = false;
            DepthStencilStateDescriptor.StencilReadMask              = D3D10_DEFAULT_STENCIL_READ_MASK;
            DepthStencilStateDescriptor.StencilWriteMask             = D3D10_DEFAULT_STENCIL_WRITE_MASK;
            DepthStencilStateDescriptor.FrontFace.StencilFailOp      = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.FrontFace.StencilPassOp      = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.FrontFace.StencilFunc        = D3D10_COMPARISON_ALWAYS;
            DepthStencilStateDescriptor.BackFace .StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.BackFace .StencilPassOp      = D3D10_STENCIL_OP_KEEP;
            DepthStencilStateDescriptor.BackFace .StencilFunc        = D3D10_COMPARISON_ALWAYS;

            Result = pNativeDevice->CreateDepthStencilState(&DepthStencilStateDescriptor, &pNativeDepthOffDepthStencilState);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create depth stencil state.");
            }

            // -----------------------------------------------------------------------------
            // Create a texture sampler state.
            // -----------------------------------------------------------------------------
            D3D10_SAMPLER_DESC SamplerDescriptor;

            SamplerDescriptor.Filter         = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
            SamplerDescriptor.AddressU       = D3D10_TEXTURE_ADDRESS_CLAMP;
            SamplerDescriptor.AddressV       = D3D10_TEXTURE_ADDRESS_CLAMP;
            SamplerDescriptor.AddressW       = D3D10_TEXTURE_ADDRESS_CLAMP;
            SamplerDescriptor.MinLOD         = 0.0f;
            SamplerDescriptor.MaxLOD         = FLT_MAX;
            SamplerDescriptor.MipLODBias     = 0.0f;
            SamplerDescriptor.MaxAnisotropy  = 4;
            SamplerDescriptor.ComparisonFunc = D3D10_COMPARISON_NEVER;
            SamplerDescriptor.BorderColor[0] = 0.0f;
            SamplerDescriptor.BorderColor[1] = 0.0f;
            SamplerDescriptor.BorderColor[2] = 0.0f;
            SamplerDescriptor.BorderColor[3] = 0.0f;

            Result = pNativeDevice->CreateSamplerState(&SamplerDescriptor, &pNativeSamplerState);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create texture sampler state.");
            }

            // -----------------------------------------------------------------------------
            // Create the constant buffer for the constants modified per frame.
            // -----------------------------------------------------------------------------
            D3D10_BUFFER_DESC PerFrameBufferDescriptor;

            PerFrameBufferDescriptor.ByteWidth      = sizeof(SPerFrameVSBuffer);
            PerFrameBufferDescriptor.Usage          = D3D10_USAGE_DYNAMIC;
            PerFrameBufferDescriptor.BindFlags      = D3D10_BIND_CONSTANT_BUFFER;
            PerFrameBufferDescriptor.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
            PerFrameBufferDescriptor.MiscFlags      = 0;

            Result = pNativeDevice->CreateBuffer(&PerFrameBufferDescriptor, 0, &pNativePerFrameVSBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create per frame vertex shader constant buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create the constant buffer for the constants modified per frame.
            // -----------------------------------------------------------------------------
            PerFrameBufferDescriptor.ByteWidth      = sizeof(SPerFramePSBuffer);
            PerFrameBufferDescriptor.Usage          = D3D10_USAGE_DYNAMIC;
            PerFrameBufferDescriptor.BindFlags      = D3D10_BIND_CONSTANT_BUFFER;
            PerFrameBufferDescriptor.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
            PerFrameBufferDescriptor.MiscFlags      = 0;

            Result = pNativeDevice->CreateBuffer(&PerFrameBufferDescriptor, 0, &pNativePerFramePSBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create per frame pixel shader constant buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create the constant buffer for the constants modified per draw call.
            // -----------------------------------------------------------------------------
            D3D10_BUFFER_DESC PerDrawCallBufferDescriptor;

            PerDrawCallBufferDescriptor.ByteWidth      = sizeof(SPerDrawCallVSBuffer);
            PerDrawCallBufferDescriptor.Usage          = D3D10_USAGE_DYNAMIC;
            PerDrawCallBufferDescriptor.BindFlags      = D3D10_BIND_CONSTANT_BUFFER;
            PerDrawCallBufferDescriptor.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
            PerDrawCallBufferDescriptor.MiscFlags      = 0;

            Result = pNativeDevice->CreateBuffer(&PerDrawCallBufferDescriptor, 0, &pNativePerDrawCallVSBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create per draw call vertex shader constant buffer.");
            }

            // -----------------------------------------------------------------------------
            // Compile the shader.
            // -----------------------------------------------------------------------------
            for (IndexOfMaterial = 0, IndexOfInputLayout = 0; IndexOfMaterial < s_NumberOfMaterials; ++ IndexOfMaterial, IndexOfInputLayout += NumberOfElements)
            {
                Result = ::D3DX10CompileFromMemory(g_Shader, strlen(g_Shader), 0, 0, 0, s_VertexShader[IndexOfMaterial], "vs_4_0", D3D10_SHADER_OPTIMIZATION_LEVEL3, 0, 0, &pNativeVertexShaderBlobs[IndexOfMaterial], &pNativeErrorBlob, 0);

                if (pNativeErrorBlob != 0)
                {
                    WriteErrorMessage(reinterpret_cast<char*>(pNativeErrorBlob->GetBufferPointer()));

                    SAFE_RELEASE(pNativeErrorBlob);
                }

                if (Result != S_OK)
                {
                    throw std::exception("Failed to compile vertex shader.");
                }

                Result = pNativeDevice->CreateVertexShader(pNativeVertexShaderBlobs[IndexOfMaterial]->GetBufferPointer(), pNativeVertexShaderBlobs[IndexOfMaterial]->GetBufferSize(), &pNativeVertexShader[IndexOfMaterial]);

                if (Result != S_OK)
                {
                    throw std::exception("Failed to create vertex shader.");
                }

                Result = ::D3DX10CompileFromMemory(g_Shader, strlen(g_Shader), 0, 0, 0, s_PixelShader[IndexOfMaterial], "ps_4_0", D3D10_SHADER_OPTIMIZATION_LEVEL3, 0, 0, &pNativePixelShaderBlobs[IndexOfMaterial], &pNativeErrorBlob, 0);

                if (pNativeErrorBlob != 0)
                {
                    WriteErrorMessage(reinterpret_cast<char*>(pNativeErrorBlob->GetBufferPointer()));

                    SAFE_RELEASE(pNativeErrorBlob);
                }

                if (Result != S_OK)
                {
                    throw std::exception("Failed to compile pixel shader.");
                }

                Result = pNativeDevice->CreatePixelShader(pNativePixelShaderBlobs[IndexOfMaterial]->GetBufferPointer(), pNativePixelShaderBlobs[IndexOfMaterial]->GetBufferSize(), &pNativePixelShader[IndexOfMaterial]);

                if (Result != S_OK)
                {
                    throw std::exception("Failed to create pixel shader.");
                }

                NumberOfElements = s_NumberOfElements[IndexOfMaterial];

                Result = pNativeDevice->CreateInputLayout(&s_InputLayouts[IndexOfInputLayout], NumberOfElements, pNativeVertexShaderBlobs[IndexOfMaterial]->GetBufferPointer(), pNativeVertexShaderBlobs[IndexOfMaterial]->GetBufferSize(), &pNativeInputLayouts[IndexOfMaterial]);

                if (Result != S_OK)
                {
                    throw std::exception("Failed to create input layout.");
                }
            }

            // -----------------------------------------------------------------------------
            // Allocate the resources.
            // -----------------------------------------------------------------------------
            for (IndexOfMaterial = 0; IndexOfMaterial < s_NumberOfMaterials; ++ IndexOfMaterial)
            {
                pVertexShader[IndexOfMaterial] = AllocateVertexShader();
                pPixelShader [IndexOfMaterial] = AllocatePixelShader ();
                pInputLayouts[IndexOfMaterial] = AllocateInputLayout ();
            }

            // -----------------------------------------------------------------------------
            // We are safe now so set the members.
            // -----------------------------------------------------------------------------
            m_Width                            = Width;
            m_Height                           = Height;
            m_pNativeDevice                    = pNativeDevice;
            m_pNativeSwapChain                 = pNativeSwapChain;
            m_pNativeFactory                   = pNativeFactory;
            m_pNativeColorBuffer               = pNativeColorBuffer;
            m_pNativeColorBufferView           = pNativeColorBufferView;
            m_pNativeDepthBuffer               = pNativeDepthBuffer;
            m_pNativeDepthBufferView           = pNativeDepthBufferView;
            m_pNativeSolidRasterizerState      = pNativeSolidRasterizerState;
            m_pNativeWireFrameRasterizerState  = pNativeWireFrameRasterizerState;
            m_pNativeDepthOnDepthStencilState  = pNativeDepthOnDepthStencilState;
            m_pNativeDepthOffDepthStencilState = pNativeDepthOffDepthStencilState;
            m_pNativeSamplerState              = pNativeSamplerState;
            m_pNativePerFrameVSBuffer          = pNativePerFrameVSBuffer;
            m_pNativePerFramePSBuffer          = pNativePerFramePSBuffer;
            m_pNativePerDrawCallVSBuffer       = pNativePerDrawCallVSBuffer;

            for (IndexOfMaterial = 0; IndexOfMaterial < s_NumberOfMaterials; ++ IndexOfMaterial)
            {
                pVertexShader[IndexOfMaterial]->m_pNativeVertexShaderBlob = pNativeVertexShaderBlobs[IndexOfMaterial];
                pVertexShader[IndexOfMaterial]->m_pNativeVertexShader     = pNativeVertexShader     [IndexOfMaterial];
                pPixelShader [IndexOfMaterial]->m_pNativePixelShaderBlob  = pNativePixelShaderBlobs [IndexOfMaterial];
                pPixelShader [IndexOfMaterial]->m_pNativePixelShader      = pNativePixelShader      [IndexOfMaterial];
                pInputLayouts[IndexOfMaterial]->m_pNativeInputLayout      = pNativeInputLayouts     [IndexOfMaterial];

                m_pVertexShader[IndexOfMaterial] = pVertexShader[IndexOfMaterial];
                m_pPixelShader [IndexOfMaterial] = pPixelShader [IndexOfMaterial];
                m_pInputLayouts[IndexOfMaterial] = pInputLayouts[IndexOfMaterial];
            }

            // -----------------------------------------------------------------------------
            // Tell DirectX, that it shall render the scene to our color buffer.
            // -----------------------------------------------------------------------------
            pNativeDevice->OMSetRenderTargets(1, &pNativeColorBufferView, pNativeDepthBufferView);

            // -----------------------------------------------------------------------------
            // Set the view port.
            // -----------------------------------------------------------------------------
            SetViewPort(Width, Height);

            // -----------------------------------------------------------------------------
            // Set the default rasterizer state.
            // -----------------------------------------------------------------------------
            SetWireFrame(false);

            // -----------------------------------------------------------------------------
            // Set the default depth stencil state.
            // -----------------------------------------------------------------------------
            SetDepthTest(true);
        }
        catch (const std::exception& _rException)
        {
            for (IndexOfMaterial = 0; IndexOfMaterial < s_NumberOfMaterials; ++ IndexOfMaterial)
            {
                SAFE_RELEASE(pNativeVertexShaderBlobs[IndexOfMaterial]);
                SAFE_RELEASE(pNativeVertexShader     [IndexOfMaterial]);
                SAFE_RELEASE(pNativePixelShaderBlobs [IndexOfMaterial]);
                SAFE_RELEASE(pNativePixelShader      [IndexOfMaterial]);
                SAFE_RELEASE(pNativeInputLayouts     [IndexOfMaterial]);

                if (pVertexShader[IndexOfMaterial] != 0) FreeVertexShader(pVertexShader[IndexOfMaterial]);
                if (pPixelShader [IndexOfMaterial] != 0) FreePixelShader (pPixelShader [IndexOfMaterial]);
                if (pInputLayouts[IndexOfMaterial] != 0) FreeInputLayout (pInputLayouts[IndexOfMaterial]);
            }

            SAFE_RELEASE(pNativePerFrameVSBuffer         );
            SAFE_RELEASE(pNativePerFramePSBuffer         );
            SAFE_RELEASE(pNativePerDrawCallVSBuffer      );
            SAFE_RELEASE(pNativeSamplerState             );
            SAFE_RELEASE(pNativeSolidRasterizerState     );
            SAFE_RELEASE(pNativeWireFrameRasterizerState );
            SAFE_RELEASE(pNativeDepthOnDepthStencilState );
            SAFE_RELEASE(pNativeDepthOffDepthStencilState);
            SAFE_RELEASE(pNativeDepthBufferView          );
            SAFE_RELEASE(pNativeDepthBuffer              );
            SAFE_RELEASE(pNativeColorBufferView          );
            SAFE_RELEASE(pNativeColorBuffer              );
            SAFE_RELEASE(pNativeSwapChain                );
            SAFE_RELEASE(pNativeFactory                  );
            SAFE_RELEASE(pNativeDevice                   );

            WriteErrorMessage(_rException.what());

        	return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::ShutdownDirectX()
    {
        int IndexOfResource;

        for (IndexOfResource = 0; IndexOfResource < s_NumberOfMaterials; ++ IndexOfResource)
        {
            if (m_pVertexShader[IndexOfResource] != 0)
            {
                FreeVertexShader(m_pVertexShader[IndexOfResource]);
                
                m_pVertexShader[IndexOfResource] = 0;
            }

            if (m_pPixelShader[IndexOfResource] != 0)
            {
                FreePixelShader(m_pPixelShader[IndexOfResource]);
                
                m_pPixelShader[IndexOfResource] = 0;
            }

            if (m_pInputLayouts[IndexOfResource] != 0)
            {
                FreeInputLayout(m_pInputLayouts[IndexOfResource]);

                m_pInputLayouts[IndexOfResource] = 0;
            }
        }

        SAFE_RELEASE(m_pNativePerFrameVSBuffer         );
        SAFE_RELEASE(m_pNativePerFramePSBuffer         );
        SAFE_RELEASE(m_pNativePerDrawCallVSBuffer      );
        SAFE_RELEASE(m_pNativeSamplerState             );
        SAFE_RELEASE(m_pNativeWireFrameRasterizerState );
        SAFE_RELEASE(m_pNativeSolidRasterizerState     );
        SAFE_RELEASE(m_pNativeDepthOffDepthStencilState);
        SAFE_RELEASE(m_pNativeDepthOnDepthStencilState );
        SAFE_RELEASE(m_pNativeDepthBufferView          );
        SAFE_RELEASE(m_pNativeDepthBuffer              );
        SAFE_RELEASE(m_pNativeColorBufferView          );
        SAFE_RELEASE(m_pNativeColorBuffer              );
        SAFE_RELEASE(m_pNativeSwapChain                );
        SAFE_RELEASE(m_pNativeFactory                  );
        SAFE_RELEASE(m_pNativeDevice                   );

        assert(IsEmpty(m_VertexShader));
        assert(IsEmpty(m_PixelShader ));
        assert(IsEmpty(m_InputLayouts));
        assert(IsEmpty(m_Textures2D  ));
        assert(IsEmpty(m_Meshes      ));

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::RunApplication(IApplication* _pApplication)
    {
        int State;

        assert(m_pNativeApplication != 0);
        assert(m_pNativeWindow      != 0);
        assert(m_pNativeDevice      != 0);

        State          = 0;
        m_pApplication = _pApplication;

        try
        {
            // -----------------------------------------------------------------------------
            // Startup the application.
            // -----------------------------------------------------------------------------
            if (!_pApplication->OnStartup())
            {
                throw std::exception("Failed to startup application.");
            }

            ++ State;

            // -----------------------------------------------------------------------------
            // Create DirectX resources.
            // -----------------------------------------------------------------------------
            if (!_pApplication->OnCreateTextures())
            {
                throw std::exception("Failed to create textures.");
            }

            ++ State;

            if (!_pApplication->OnCreateMeshes())
            {
                throw std::exception("Failed to create meshes.");
            }

            ++ State;

            if (!_pApplication->OnCreateObjects())
            {
                throw std::exception("Failed to create objects.");
            }

            ++ State;

            // -----------------------------------------------------------------------------
            // Show up the window.
            // -----------------------------------------------------------------------------
            ShowWindow  (m_pNativeWindow, SW_SHOWDEFAULT);
            UpdateWindow(m_pNativeWindow);

            // -----------------------------------------------------------------------------
            // The main loop of our application, which dispatches all the event messages
            // created by out window, e.h. resizing, update, ...
            // -----------------------------------------------------------------------------
            MSG Message;

            memset(&Message, 0, sizeof(Message));

            while (Message.message != WM_QUIT)
            {
                if (PeekMessage(&Message, 0, 0U, 0U, PM_REMOVE))
                {
                    TranslateMessage(&Message);
                    DispatchMessage (&Message);
                }
                else
                {
                    // -----------------------------------------------------------------------------
                    // Update render specific data such as our camera.
                    // -----------------------------------------------------------------------------
                    if (!_pApplication->OnUpdate())
                    {
                        throw std::exception("Failed to update the application.");
                    }

                    // -----------------------------------------------------------------------------
                    // Render our scene.
                    // -----------------------------------------------------------------------------
                    BeginFrame();

                    if (!_pApplication->OnFrame())
                    {
                        throw std::exception("Failed to draw the scene.");
                    }

                    EndFrame();
                }
            }

            // -----------------------------------------------------------------------------
            // Release DirectX resources.
            // -----------------------------------------------------------------------------
            if (!_pApplication->OnReleaseObjects())
            {
                throw std::exception("Failed to release objects.");
            }

            if (!_pApplication->OnReleaseMeshes())
            {
                throw std::exception("Failed to release meshes.");
            }

            if (!_pApplication->OnReleaseTextures())
            {
                throw std::exception("Failed to release textures.");
            }

            // -----------------------------------------------------------------------------
            // Shutdown the application.
            // -----------------------------------------------------------------------------
            if (!_pApplication->OnShutdown())
            {
                throw std::exception("Failed to shutdown the application.");
            }
        }
        catch (const std::exception& _rException)
        {
            switch (State)
            {
                case 4: _pApplication->OnReleaseObjects ();
                case 3: _pApplication->OnReleaseMeshes  ();
                case 2: _pApplication->OnReleaseTextures();
                case 1: _pApplication->OnShutdown       ();
            }

            WriteErrorMessage(_rException.what());

            m_pApplication = 0;

            return false;
        }

        m_pApplication = 0;

        return true;
    }

    // -----------------------------------------------------------------------------

    long CYoshiX::ProcessMessages(HWND _NativeWindowHandle, unsigned int _MessageType, unsigned int _Arg1, long _Arg2)
    {
        int  MouseX;
        int  MouseY;
        int  Button;
        int  WheelDelta;
        bool IsDown;
        bool IsDoubleClick;

        switch (_MessageType)
        {
            case WM_KEYDOWN:
            case WM_SYSKEYDOWN:
            case WM_KEYUP:
            case WM_SYSKEYUP:
            {
                IsDown = (_MessageType == WM_KEYDOWN) || (_MessageType == WM_SYSKEYDOWN);

                GetInstance().m_pApplication->OnKeyEvent(_Arg1, IsDown, (_Arg2 & (1UL << 29)) != 0);
            }
            break;

            case WM_LBUTTONDOWN:
            case WM_LBUTTONUP:
            case WM_LBUTTONDBLCLK:
            {
                MouseX        = GET_X_LPARAM(_Arg2);
                MouseY        = GET_Y_LPARAM(_Arg2);
                Button        = 0;
                IsDown        = _MessageType == WM_LBUTTONDOWN;
                IsDoubleClick = _MessageType == WM_LBUTTONDBLCLK;
                WheelDelta    = 0;

                GetInstance().m_pApplication->OnMouseEvent(MouseX, MouseY, Button, IsDown, IsDoubleClick, WheelDelta);
            }
            break;

            case WM_MBUTTONDOWN:
            case WM_MBUTTONUP:
            case WM_MBUTTONDBLCLK:
            {
                MouseX        = GET_X_LPARAM(_Arg2);
                MouseY        = GET_Y_LPARAM(_Arg2);
                Button        = 1;
                IsDown        = _MessageType == WM_MBUTTONDOWN;
                IsDoubleClick = _MessageType == WM_MBUTTONDBLCLK;
                WheelDelta    = 0;

                GetInstance().m_pApplication->OnMouseEvent(MouseX, MouseY, Button, IsDown, IsDoubleClick, WheelDelta);
            }
            break;

            case WM_RBUTTONDOWN:
            case WM_RBUTTONUP:
            case WM_RBUTTONDBLCLK:
            {
                MouseX        = GET_X_LPARAM(_Arg2);
                MouseY        = GET_Y_LPARAM(_Arg2);
                Button        = 2;
                IsDown        = _MessageType == WM_RBUTTONDOWN;
                IsDoubleClick = _MessageType == WM_RBUTTONDBLCLK;
                WheelDelta    = 0;

                GetInstance().m_pApplication->OnMouseEvent(MouseX, MouseY, Button, IsDown, IsDoubleClick, WheelDelta);
            }
            break;

            case WM_MOUSEWHEEL:
            {
                MouseX        = GET_X_LPARAM(_Arg2);
                MouseY        = GET_Y_LPARAM(_Arg2);
                Button        = -1;
                IsDown        = false;
                IsDoubleClick = false;
                WheelDelta    = GET_WHEEL_DELTA_WPARAM(_Arg1);

                GetInstance().m_pApplication->OnMouseEvent(MouseX, MouseY, Button, IsDown, IsDoubleClick, WheelDelta);
            }
            break;

            case WM_MOUSEMOVE:
            {
                MouseX        = GET_X_LPARAM(_Arg2);
                MouseY        = GET_Y_LPARAM(_Arg2);
                Button        = -1;
                IsDown        = false;
                IsDoubleClick = false;
                WheelDelta    = 0;

                GetInstance().m_pApplication->OnMouseEvent(MouseX, MouseY, Button, IsDown, IsDoubleClick, WheelDelta);
            }
            break;

            case WM_PAINT:
            {
                // -----------------------------------------------------------------------------
                // Tell the operating system to repaint the window.
                // -----------------------------------------------------------------------------
                PAINTSTRUCT PaintInfo;

                BeginPaint(_NativeWindowHandle, &PaintInfo);
                EndPaint  (_NativeWindowHandle, &PaintInfo);
            }
            break;

            case WM_SIZE:
            {
                CYoshiX& rInstance = GetInstance();

                rInstance.OnResizeWindow();

                rInstance.m_pApplication->OnResize(rInstance.m_Width, rInstance.m_Height);
            }
            break;

            case WM_DESTROY:
            {
                // -----------------------------------------------------------------------------
                // Tell the operating system to leave the application.
                // -----------------------------------------------------------------------------
                PostQuitMessage(0);

                break;
            }

            default:
            {
                // -----------------------------------------------------------------------------
                // Let the operating system handle all the messages we do not want to handle.
                // -----------------------------------------------------------------------------
                return DefWindowProc(_NativeWindowHandle, _MessageType, _Arg1, _Arg2);
            }
        }

        return 0;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::SetDepthTest(bool _Flag)
    {
        assert(m_pNativeDevice != 0);

        if (_Flag)
        {
            m_pNativeDevice->OMSetDepthStencilState(m_pNativeDepthOnDepthStencilState, 1);
        }
        else
        {
            m_pNativeDevice->OMSetDepthStencilState(m_pNativeDepthOffDepthStencilState, 1);
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::SetWireFrame(bool _Flag)
    {
        assert(m_pNativeDevice != 0);

        if (_Flag)
        {
            m_pNativeDevice->RSSetState(m_pNativeWireFrameRasterizerState);
        }
        else
        {
            m_pNativeDevice->RSSetState(m_pNativeSolidRasterizerState);
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    void CYoshiX::SetClearColor(const float* _pColor)
    {
        ::memcpy(m_ClearColor, _pColor, sizeof(m_ClearColor));
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::CreateTexture(const char* _pPath, BHandle* _ppTexture)
    {
        CInternTexture2D*         pTexture;

        HRESULT                   Result;
        ID3D10Texture2D*          pNativeTexture;
        ID3D10ShaderResourceView* pNativeTextureView;

        assert(m_pNativeDevice != 0);

        *_ppTexture = 0;

        pNativeTexture     = 0;
        pNativeTextureView = 0;

        try
        {
            //--------------------------------------------------------------------------------------
            // Load the texture from a file and create a DirectX resource.
            //--------------------------------------------------------------------------------------
            Result = D3DX10CreateTextureFromFileA(m_pNativeDevice, _pPath, 0, 0, reinterpret_cast<ID3D10Resource**>(&pNativeTexture), 0);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create texture.");
            }

            //--------------------------------------------------------------------------------------
            // Create a resource view for the texture. From the view of DirectX 10 resources are
            // just junks of memory without any type information. The view defines how the GPU has
            // to interpret a resource chunk. In this case we tell DirectX to interpret the chunk
            // allocated above - via D3DX10CreateTextureFromFile - to interpret as a 2D texture.
            //--------------------------------------------------------------------------------------
            D3D10_TEXTURE2D_DESC            TextureDescriptor;
            D3D10_SHADER_RESOURCE_VIEW_DESC TextureViewDescriptor;

            pNativeTexture->GetDesc(&TextureDescriptor);

            TextureViewDescriptor.Format                    = TextureDescriptor.Format;
            TextureViewDescriptor.ViewDimension             = D3D10_SRV_DIMENSION_TEXTURE2D;
            TextureViewDescriptor.Texture2D.MipLevels       = TextureDescriptor.MipLevels;
            TextureViewDescriptor.Texture2D.MostDetailedMip = TextureDescriptor.MipLevels - 1;
            TextureViewDescriptor.Buffer.ElementOffset      = 0;
            TextureViewDescriptor.Buffer.ElementWidth       = 1;
            TextureViewDescriptor.Buffer.FirstElement       = 0;
            TextureViewDescriptor.Buffer.NumElements        = 1;

            Result = m_pNativeDevice->CreateShaderResourceView(pNativeTexture, &TextureViewDescriptor, &pNativeTextureView);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create texture view.");
            }

            // -----------------------------------------------------------------------------
            // Setup the texture.
            // -----------------------------------------------------------------------------
            pTexture = AllocateTexture2D();

            pTexture->m_pNativeTexture     = pNativeTexture;
            pTexture->m_pNativeTextureView = pNativeTextureView;

            *_ppTexture = pTexture;
        }
        catch (...)
        {
            SAFE_RELEASE(pNativeTexture    );
            SAFE_RELEASE(pNativeTextureView);

            return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::ReleaseTexture(BHandle _pTexture)
    {
        assert(_pTexture != 0);

        FreeTexture2D(static_cast<CInternTexture2D*>(_pTexture));

        return false;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::CreateMesh(const float* _pVertices, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    {
        struct SVertex
        {
            float m_PX;
            float m_PY;
            float m_PZ;
        };

        CInternMesh*  pMesh;

        int           IndexOfVertex;
        SVertex*      pVertices;
        int*          pIndices;

        HRESULT       Result;
        ID3D10Buffer* pNativeVertexBuffer;
        ID3D10Buffer* pNativeIndexBuffer;

        assert(m_pNativeDevice != 0);
        assert(_pVertices != 0);
        assert(_NumberOfVertices > 0);
        assert(_pIndices != 0);
        assert(_NumberOfIndices > 0);
        assert(_ppMesh != 0);

        *_ppMesh            = 0;

        pVertices           = 0;
        pIndices            = 0;

        pNativeVertexBuffer = 0;
        pNativeIndexBuffer  = 0;

        try
        {
            // -----------------------------------------------------------------------------
            // Prepare and copy the data for upload.
            // -----------------------------------------------------------------------------
            pVertices = new SVertex[_NumberOfVertices];
            pIndices  = new int    [_NumberOfIndices ];

            for (IndexOfVertex = 0; IndexOfVertex < _NumberOfVertices; ++ IndexOfVertex)
            {
                SVertex& rVertex = pVertices[IndexOfVertex];

                rVertex.m_PX = _pVertices[IndexOfVertex * 3 + 0];
                rVertex.m_PY = _pVertices[IndexOfVertex * 3 + 1];
                rVertex.m_PZ = _pVertices[IndexOfVertex * 3 + 2];
            }

            memcpy(pIndices, _pIndices, _NumberOfIndices * sizeof(*pIndices));

            // -----------------------------------------------------------------------------
            // Create the vertex buffer on the GPU.
            // -----------------------------------------------------------------------------
            D3D10_BUFFER_DESC BufferDescriptor;

            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfVertices * sizeof(*pVertices);
            BufferDescriptor.BindFlags      = D3D10_BIND_VERTEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            D3D10_SUBRESOURCE_DATA Data;

            Data.pSysMem = pVertices;

            // -----------------------------------------------------------------------------
            // Upload the vertices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeVertexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create vertex buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create the index buffer on the GPU.
            // -----------------------------------------------------------------------------
            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfIndices * sizeof(_pIndices);
            BufferDescriptor.BindFlags      = D3D10_BIND_INDEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            Data.pSysMem = pIndices;

            // -----------------------------------------------------------------------------
            // Upload the indices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeIndexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create index buffer.");
            }

            // -----------------------------------------------------------------------------
            // Setup the mesh.
            // -----------------------------------------------------------------------------
            pMesh = AllocateMesh();

            pMesh->m_pVertices              = pVertices;
            pMesh->m_NumberOfVertices       = _NumberOfVertices;
            pMesh->m_NumberOfBytesPerVertex = sizeof(*pVertices);
            pMesh->m_pIndices               = pIndices;
            pMesh->m_NumberOfIndices        = _NumberOfIndices;
            pMesh->m_pNativeVertexBuffer    = pNativeVertexBuffer;
            pMesh->m_pNativeIndexBuffer     = pNativeIndexBuffer;
            pMesh->m_VertexShaderPtr        = m_pVertexShader[Default];
            pMesh->m_PixelShaderPtr         = m_pPixelShader [Default];
            pMesh->m_InputLayoutPtr         = m_pInputLayouts[Default];
            pMesh->m_TexturePtr             = 0;

            *_ppMesh = pMesh;
        }
        catch (const std::exception& _rException)
        {
        	if (pVertices != 0) delete[] pVertices;
            if (pIndices  != 0) delete[] pIndices;

            SAFE_RELEASE(pNativeVertexBuffer);
            SAFE_RELEASE(pNativeIndexBuffer );

            WriteErrorMessage(_rException.what());

            return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::CreateMesh(const float* _pVertices, const float* _pNormals, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    {
        struct SVertex
        {
            float m_PX;
            float m_PY;
            float m_PZ;
            float m_NX;
            float m_NY;
            float m_NZ;
        };

        CInternMesh*  pMesh;

        int           IndexOfVertex;
        SVertex*      pVertices;
        int*          pIndices;

        HRESULT       Result;
        ID3D10Buffer* pNativeVertexBuffer;
        ID3D10Buffer* pNativeIndexBuffer;

        assert(m_pNativeDevice != 0);
        assert(_pVertices != 0);
        assert(_pNormals != 0);
        assert(_NumberOfVertices > 0);
        assert(_pIndices != 0);
        assert(_NumberOfIndices > 0);
        assert(_ppMesh != 0);

        *_ppMesh            = 0;

        pVertices           = 0;
        pIndices            = 0;

        pNativeVertexBuffer = 0;
        pNativeIndexBuffer  = 0;

        try
        {
            // -----------------------------------------------------------------------------
            // Prepare and copy the data for upload.
            // -----------------------------------------------------------------------------
            pVertices = new SVertex[_NumberOfVertices];
            pIndices  = new int    [_NumberOfIndices ];

            for (IndexOfVertex = 0; IndexOfVertex < _NumberOfVertices; ++ IndexOfVertex)
            {
                SVertex& rVertex = pVertices[IndexOfVertex];

                rVertex.m_PX = _pVertices[IndexOfVertex * 3 + 0];
                rVertex.m_PY = _pVertices[IndexOfVertex * 3 + 1];
                rVertex.m_PZ = _pVertices[IndexOfVertex * 3 + 2];
                rVertex.m_NX = _pNormals [IndexOfVertex * 3 + 0];
                rVertex.m_NY = _pNormals [IndexOfVertex * 3 + 1];
                rVertex.m_NZ = _pNormals [IndexOfVertex * 3 + 2];
            }

            memcpy(pIndices, _pIndices, _NumberOfIndices * sizeof(*pIndices));

            // -----------------------------------------------------------------------------
            // Create the vertex buffer on the GPU.
            // -----------------------------------------------------------------------------
            D3D10_BUFFER_DESC BufferDescriptor;

            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfVertices * sizeof(*pVertices);
            BufferDescriptor.BindFlags      = D3D10_BIND_VERTEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            D3D10_SUBRESOURCE_DATA Data;

            Data.pSysMem = pVertices;

            // -----------------------------------------------------------------------------
            // Upload the vertices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeVertexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create vertex buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create the index buffer on the GPU.
            // -----------------------------------------------------------------------------
            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfIndices * sizeof(_pIndices);
            BufferDescriptor.BindFlags      = D3D10_BIND_INDEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            Data.pSysMem = pIndices;

            // -----------------------------------------------------------------------------
            // Upload the indices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeIndexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create index buffer.");
            }

            // -----------------------------------------------------------------------------
            // Setup the mesh.
            // -----------------------------------------------------------------------------
            pMesh = AllocateMesh();

            pMesh->m_pVertices              = pVertices;
            pMesh->m_NumberOfVertices       = _NumberOfVertices;
            pMesh->m_NumberOfBytesPerVertex = sizeof(*pVertices);
            pMesh->m_pIndices               = pIndices;
            pMesh->m_NumberOfIndices        = _NumberOfIndices;
            pMesh->m_pNativeVertexBuffer    = pNativeVertexBuffer;
            pMesh->m_pNativeIndexBuffer     = pNativeIndexBuffer;
            pMesh->m_VertexShaderPtr        = m_pVertexShader[DefaultIlluminated];
            pMesh->m_PixelShaderPtr         = m_pPixelShader [DefaultIlluminated];
            pMesh->m_InputLayoutPtr         = m_pInputLayouts[DefaultIlluminated];
            pMesh->m_TexturePtr             = 0;

            *_ppMesh = pMesh;
        }
        catch (const std::exception& _rException)
        {
            if (pVertices != 0) delete[] pVertices;
            if (pIndices  != 0) delete[] pIndices;

            SAFE_RELEASE(pNativeVertexBuffer);
            SAFE_RELEASE(pNativeIndexBuffer );

            WriteErrorMessage(_rException.what());

            return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::CreateColoredMesh(const float* _pVertices, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    {
        struct SVertex
        {
            float m_PX;
            float m_PY;
            float m_PZ;
            float m_CR;
            float m_CG;
            float m_CB;
            float m_CA;
        };

        CInternMesh*  pMesh;

        int           IndexOfVertex;
        SVertex*      pVertices;
        int*          pIndices;

        HRESULT       Result;
        ID3D10Buffer* pNativeVertexBuffer;
        ID3D10Buffer* pNativeIndexBuffer;

        assert(m_pNativeDevice != 0);
        assert(_pVertices != 0);
        assert(_pColors != 0);
        assert(_NumberOfVertices > 0);
        assert(_pIndices != 0);
        assert(_NumberOfIndices > 0);
        assert(_ppMesh != 0);

        *_ppMesh            = 0;

        pVertices           = 0;
        pIndices            = 0;

        pNativeVertexBuffer = 0;
        pNativeIndexBuffer  = 0;

        try
        {
            // -----------------------------------------------------------------------------
            // Prepare and copy the data for upload.
            // -----------------------------------------------------------------------------
            pVertices = new SVertex[_NumberOfVertices];
            pIndices  = new int    [_NumberOfIndices ];

            for (IndexOfVertex = 0; IndexOfVertex < _NumberOfVertices; ++ IndexOfVertex)
            {
                SVertex& rVertex = pVertices[IndexOfVertex];

                rVertex.m_PX = _pVertices[IndexOfVertex * 3 + 0];
                rVertex.m_PY = _pVertices[IndexOfVertex * 3 + 1];
                rVertex.m_PZ = _pVertices[IndexOfVertex * 3 + 2];
                rVertex.m_CR = _pColors  [IndexOfVertex * 4 + 0];
                rVertex.m_CG = _pColors  [IndexOfVertex * 4 + 1];
                rVertex.m_CB = _pColors  [IndexOfVertex * 4 + 2];
                rVertex.m_CA = _pColors  [IndexOfVertex * 4 + 3];
            }

            memcpy(pIndices, _pIndices, _NumberOfIndices * sizeof(*pIndices));

            // -----------------------------------------------------------------------------
            // Create the vertex buffer on the GPU.
            // -----------------------------------------------------------------------------
            D3D10_BUFFER_DESC BufferDescriptor;

            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfVertices * sizeof(*pVertices);
            BufferDescriptor.BindFlags      = D3D10_BIND_VERTEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            D3D10_SUBRESOURCE_DATA Data;

            Data.pSysMem = pVertices;

            // -----------------------------------------------------------------------------
            // Upload the vertices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeVertexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create vertex buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create the index buffer on the GPU.
            // -----------------------------------------------------------------------------
            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfIndices * sizeof(_pIndices);
            BufferDescriptor.BindFlags      = D3D10_BIND_INDEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            Data.pSysMem = pIndices;

            // -----------------------------------------------------------------------------
            // Upload the indices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeIndexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create index buffer.");
            }

            // -----------------------------------------------------------------------------
            // Setup the mesh.
            // -----------------------------------------------------------------------------
            pMesh = AllocateMesh();

            pMesh->m_pVertices              = pVertices;
            pMesh->m_NumberOfVertices       = _NumberOfVertices;
            pMesh->m_NumberOfBytesPerVertex = sizeof(*pVertices);
            pMesh->m_pIndices               = pIndices;
            pMesh->m_NumberOfIndices        = _NumberOfIndices;
            pMesh->m_pNativeVertexBuffer    = pNativeVertexBuffer;
            pMesh->m_pNativeIndexBuffer     = pNativeIndexBuffer;
            pMesh->m_VertexShaderPtr        = m_pVertexShader[Color];
            pMesh->m_PixelShaderPtr         = m_pPixelShader [Color];
            pMesh->m_InputLayoutPtr         = m_pInputLayouts[Color];
            pMesh->m_TexturePtr             = 0;

            *_ppMesh = pMesh;
        }
        catch (const std::exception& _rException)
        {
            if (pVertices != 0) delete[] pVertices;
            if (pIndices  != 0) delete[] pIndices;

            SAFE_RELEASE(pNativeVertexBuffer);
            SAFE_RELEASE(pNativeIndexBuffer );

            WriteErrorMessage(_rException.what());

            return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------


    struct SVertex
    {
        float m_PX;
        float m_PY;
        float m_PZ;
        float m_NX;
        float m_NY;
        float m_NZ;
        float m_CR;
        float m_CG;
        float m_CB;
        float m_CA;
    };


    bool CYoshiX::CreateColoredMesh(const float* _pVertices, const float* _pNormals, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    {

        CInternMesh*  pMesh;

        int           IndexOfVertex;
        SVertex*      pVertices;
        int*          pIndices;

        HRESULT       Result;
        ID3D10Buffer* pNativeVertexBuffer;
        ID3D10Buffer* pNativeIndexBuffer;

        assert(m_pNativeDevice != 0);
        assert(_pVertices != 0);
        assert(_pNormals != 0);
        assert(_pColors != 0);
        assert(_NumberOfVertices > 0);
        assert(_pIndices != 0);
        assert(_NumberOfIndices > 0);
        assert(_ppMesh != 0);

        *_ppMesh            = 0;

        pVertices           = 0;
        pIndices            = 0;

        pNativeVertexBuffer = 0;
        pNativeIndexBuffer  = 0;

        try
        {
            // -----------------------------------------------------------------------------
            // Prepare and copy the data for upload.
            // -----------------------------------------------------------------------------
            pVertices = new SVertex[_NumberOfVertices];
            pIndices  = new int    [_NumberOfIndices ];

            for (IndexOfVertex = 0; IndexOfVertex < _NumberOfVertices; ++ IndexOfVertex)
            {
                SVertex& rVertex = pVertices[IndexOfVertex];

                rVertex.m_PX = _pVertices[IndexOfVertex * 3 + 0];
                rVertex.m_PY = _pVertices[IndexOfVertex * 3 + 1];
                rVertex.m_PZ = _pVertices[IndexOfVertex * 3 + 2];
                rVertex.m_NX = _pNormals [IndexOfVertex * 3 + 0];
                rVertex.m_NY = _pNormals [IndexOfVertex * 3 + 1];
                rVertex.m_NZ = _pNormals [IndexOfVertex * 3 + 2];
                rVertex.m_CR = _pColors  [IndexOfVertex * 4 + 0];
                rVertex.m_CG = _pColors  [IndexOfVertex * 4 + 1];
                rVertex.m_CB = _pColors  [IndexOfVertex * 4 + 2];
                rVertex.m_CA = _pColors  [IndexOfVertex * 4 + 3];
            }

            memcpy(pIndices, _pIndices, _NumberOfIndices * sizeof(*pIndices));

            // -----------------------------------------------------------------------------
            // Create the vertex buffer on the GPU.
            // -----------------------------------------------------------------------------
            D3D10_BUFFER_DESC BufferDescriptor;

            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfVertices * sizeof(*pVertices);
            BufferDescriptor.BindFlags      = D3D10_BIND_VERTEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            D3D10_SUBRESOURCE_DATA Data;

            Data.pSysMem = pVertices;

            // -----------------------------------------------------------------------------
            // Upload the vertices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeVertexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create vertex buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create the index buffer on the GPU.
            // -----------------------------------------------------------------------------
            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfIndices * sizeof(_pIndices);
            BufferDescriptor.BindFlags      = D3D10_BIND_INDEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            Data.pSysMem = pIndices;

            // -----------------------------------------------------------------------------
            // Upload the indices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeIndexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create index buffer.");
            }

            // -----------------------------------------------------------------------------
            // Setup the mesh.
            // -----------------------------------------------------------------------------
            pMesh = AllocateMesh();

            pMesh->m_pVertices              = pVertices;
            pMesh->m_NumberOfVertices       = _NumberOfVertices;
            pMesh->m_NumberOfBytesPerVertex = sizeof(*pVertices);
            pMesh->m_pIndices               = pIndices;
            pMesh->m_NumberOfIndices        = _NumberOfIndices;
            pMesh->m_pNativeVertexBuffer    = pNativeVertexBuffer;
            pMesh->m_pNativeIndexBuffer     = pNativeIndexBuffer;
            pMesh->m_VertexShaderPtr        = m_pVertexShader[ColorIlluminated];
            pMesh->m_PixelShaderPtr         = m_pPixelShader [ColorIlluminated];
            pMesh->m_InputLayoutPtr         = m_pInputLayouts[ColorIlluminated];
            pMesh->m_TexturePtr             = 0;

            *_ppMesh = pMesh;
        }
        catch (const std::exception& _rException)
        {
            if (pVertices != 0) delete[] pVertices;
            if (pIndices  != 0) delete[] pIndices;

            SAFE_RELEASE(pNativeVertexBuffer);
            SAFE_RELEASE(pNativeIndexBuffer );

            WriteErrorMessage(_rException.what());

            return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::CreateTexturedMesh(const float* _pVertices, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh)
    {
        struct SVertex
        {
            float m_PX;
            float m_PY;
            float m_PZ;
            float m_TU;
            float m_TV;
        };

        CInternMesh*  pMesh;
                      
        int           IndexOfVertex;
        SVertex*      pVertices;
        int*          pIndices;
                      
        HRESULT       Result;
        ID3D10Buffer* pNativeVertexBuffer;
        ID3D10Buffer* pNativeIndexBuffer;

        assert(m_pNativeDevice != 0);
        assert(_pVertices != 0);
        assert(_pTexCoords != 0);
        assert(_NumberOfVertices > 0);
        assert(_pIndices != 0);
        assert(_NumberOfIndices > 0);
        assert(_pTexture != 0);
        assert(_ppMesh != 0);

        *_ppMesh            = 0;

        pVertices           = 0;
        pIndices            = 0;

        pNativeVertexBuffer = 0;
        pNativeIndexBuffer  = 0;

        try
        {
            // -----------------------------------------------------------------------------
            // Prepare and copy the data for upload.
            // -----------------------------------------------------------------------------
            pVertices = new SVertex[_NumberOfVertices];
            pIndices  = new int    [_NumberOfIndices ];

            for (IndexOfVertex = 0; IndexOfVertex < _NumberOfVertices; ++ IndexOfVertex)
            {
                SVertex& rVertex = pVertices[IndexOfVertex];

                rVertex.m_PX = _pVertices [IndexOfVertex * 3 + 0];
                rVertex.m_PY = _pVertices [IndexOfVertex * 3 + 1];
                rVertex.m_PZ = _pVertices [IndexOfVertex * 3 + 2];
                rVertex.m_TU = _pTexCoords[IndexOfVertex * 2 + 0];
                rVertex.m_TV = _pTexCoords[IndexOfVertex * 2 + 1];
            }

            memcpy(pIndices, _pIndices, _NumberOfIndices * sizeof(*pIndices));

            // -----------------------------------------------------------------------------
            // Create the vertex buffer on the GPU.
            // -----------------------------------------------------------------------------
            D3D10_BUFFER_DESC BufferDescriptor;

            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfVertices * sizeof(*pVertices);
            BufferDescriptor.BindFlags      = D3D10_BIND_VERTEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            D3D10_SUBRESOURCE_DATA Data;

            Data.pSysMem = pVertices;

            // -----------------------------------------------------------------------------
            // Upload the vertices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeVertexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create vertex buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create the index buffer on the GPU.
            // -----------------------------------------------------------------------------
            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfIndices * sizeof(_pIndices);
            BufferDescriptor.BindFlags      = D3D10_BIND_INDEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            Data.pSysMem = pIndices;

            // -----------------------------------------------------------------------------
            // Upload the indices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeIndexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create index buffer.");
            }

            // -----------------------------------------------------------------------------
            // Setup the mesh.
            // -----------------------------------------------------------------------------
            pMesh = AllocateMesh();

            pMesh->m_pVertices              = pVertices;
            pMesh->m_NumberOfVertices       = _NumberOfVertices;
            pMesh->m_NumberOfBytesPerVertex = sizeof(*pVertices);
            pMesh->m_pIndices               = pIndices;
            pMesh->m_NumberOfIndices        = _NumberOfIndices;
            pMesh->m_pNativeVertexBuffer    = pNativeVertexBuffer;
            pMesh->m_pNativeIndexBuffer     = pNativeIndexBuffer;
            pMesh->m_VertexShaderPtr        = m_pVertexShader[Texture];
            pMesh->m_PixelShaderPtr         = m_pPixelShader [Texture];
            pMesh->m_InputLayoutPtr         = m_pInputLayouts[Texture];
            pMesh->m_TexturePtr             = static_cast<CInternTexture2D*>(_pTexture);

            *_ppMesh = pMesh;
        }
        catch (const std::exception& _rException)
        {
            if (pVertices != 0) delete[] pVertices;
            if (pIndices  != 0) delete[] pIndices;

            SAFE_RELEASE(pNativeVertexBuffer);
            SAFE_RELEASE(pNativeIndexBuffer );

            WriteErrorMessage(_rException.what());

            return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::CreateTexturedMesh(const float* _pVertices, const float* _pNormals, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh)
    {
        struct SVertex
        {
            float m_PX;
            float m_PY;
            float m_PZ;
            float m_NX;
            float m_NY;
            float m_NZ;
            float m_TU;
            float m_TV;
        };

        CInternMesh*  pMesh;

        int           IndexOfVertex;
        SVertex*      pVertices;
        int*          pIndices;

        HRESULT       Result;
        ID3D10Buffer* pNativeVertexBuffer;
        ID3D10Buffer* pNativeIndexBuffer;

        assert(m_pNativeDevice != 0);
        assert(_pVertices != 0);
        assert(_pNormals != 0);
        assert(_pTexCoords != 0);
        assert(_NumberOfVertices > 0);
        assert(_pIndices != 0);
        assert(_NumberOfIndices > 0);
        assert(_pTexture != 0);
        assert(_ppMesh != 0);

        *_ppMesh            = 0;

        pVertices           = 0;
        pIndices            = 0;

        pNativeVertexBuffer = 0;
        pNativeIndexBuffer  = 0;

        try
        {
            // -----------------------------------------------------------------------------
            // Prepare and copy the data for upload.
            // -----------------------------------------------------------------------------
            pVertices = new SVertex[_NumberOfVertices];
            pIndices  = new int    [_NumberOfIndices ];

            for (IndexOfVertex = 0; IndexOfVertex < _NumberOfVertices; ++ IndexOfVertex)
            {
                SVertex& rVertex = pVertices[IndexOfVertex];

                rVertex.m_PX = _pVertices [IndexOfVertex * 3 + 0];
                rVertex.m_PY = _pVertices [IndexOfVertex * 3 + 1];
                rVertex.m_PZ = _pVertices [IndexOfVertex * 3 + 2];
                rVertex.m_NX = _pNormals  [IndexOfVertex * 3 + 0];
                rVertex.m_NY = _pNormals  [IndexOfVertex * 3 + 1];
                rVertex.m_NZ = _pNormals  [IndexOfVertex * 3 + 2];
                rVertex.m_TU = _pTexCoords[IndexOfVertex * 2 + 0];
                rVertex.m_TV = _pTexCoords[IndexOfVertex * 2 + 1];
            }

            memcpy(pIndices, _pIndices, _NumberOfIndices * sizeof(*pIndices));

            // -----------------------------------------------------------------------------
            // Create the vertex buffer on the GPU.
            // -----------------------------------------------------------------------------
            D3D10_BUFFER_DESC BufferDescriptor;

            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfVertices * sizeof(*pVertices);
            BufferDescriptor.BindFlags      = D3D10_BIND_VERTEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            D3D10_SUBRESOURCE_DATA Data;

            Data.pSysMem = pVertices;

            // -----------------------------------------------------------------------------
            // Upload the vertices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeVertexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create vertex buffer.");
            }

            // -----------------------------------------------------------------------------
            // Create the index buffer on the GPU.
            // -----------------------------------------------------------------------------
            BufferDescriptor.Usage          = D3D10_USAGE_DEFAULT;
            BufferDescriptor.ByteWidth      = _NumberOfIndices * sizeof(_pIndices);
            BufferDescriptor.BindFlags      = D3D10_BIND_INDEX_BUFFER;
            BufferDescriptor.CPUAccessFlags = 0;
            BufferDescriptor.MiscFlags      = 0;

            Data.pSysMem = pIndices;

            // -----------------------------------------------------------------------------
            // Upload the indices.
            // -----------------------------------------------------------------------------
            Result = m_pNativeDevice->CreateBuffer(&BufferDescriptor, &Data, &pNativeIndexBuffer);

            if (Result != S_OK)
            {
                throw std::exception("Failed to create index buffer.");
            }

            // -----------------------------------------------------------------------------
            // Setup the mesh.
            // -----------------------------------------------------------------------------
            pMesh = AllocateMesh();

            pMesh->m_pVertices              = pVertices;
            pMesh->m_NumberOfVertices       = _NumberOfVertices;
            pMesh->m_NumberOfBytesPerVertex = sizeof(*pVertices);
            pMesh->m_pIndices               = pIndices;
            pMesh->m_NumberOfIndices        = _NumberOfIndices;
            pMesh->m_pNativeVertexBuffer    = pNativeVertexBuffer;
            pMesh->m_pNativeIndexBuffer     = pNativeIndexBuffer;
            pMesh->m_VertexShaderPtr        = m_pVertexShader[TextureIlluminated];
            pMesh->m_PixelShaderPtr         = m_pPixelShader [TextureIlluminated];
            pMesh->m_InputLayoutPtr         = m_pInputLayouts[TextureIlluminated];
            pMesh->m_TexturePtr             = static_cast<CInternTexture2D*>(_pTexture);

            *_ppMesh = pMesh;
        }
        catch (const std::exception& _rException)
        {
            if (pVertices != 0) delete[] pVertices;
            if (pIndices  != 0) delete[] pIndices;

            SAFE_RELEASE(pNativeVertexBuffer);
            SAFE_RELEASE(pNativeIndexBuffer );

            WriteErrorMessage(_rException.what());

            return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::ReleaseMesh(BHandle _pMesh)
    {
        assert(_pMesh != 0);

        FreeMesh(static_cast<CInternMesh*>(_pMesh));

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::CreateObject(BHandle _pMesh, BHandle* _ppObject)
    {
        CInternObject* pObject;
        CInternMesh*   pMesh;

        assert(_pMesh    != 0);
        assert(_ppObject != 0);

        *_ppObject = 0;

        try
        {
            pMesh = static_cast<CInternMesh*>(_pMesh);

            pObject = AllocateObject();

            pObject->m_MeshPtr = pMesh;

            *_ppObject = pObject;
        }
        catch (...)
        {
            return false;
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::ReleaseObject(BHandle _pObject)
    {
        CInternObject* pObject;

        assert(_pObject != 0);

        pObject = static_cast<CInternObject*>(_pObject);

        FreeObject(pObject);

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::DrawObject(BHandle _pObject)
    {
        CObject*                  pObject;
        CMesh*                    pMesh;
        SPerDrawCallVSBuffer*     pPerDrawCallVSBuffer;
        ID3D10ShaderResourceView* pNativeTextureView;

        assert(m_pNativeDevice              != 0);
        assert(m_pNativePerDrawCallVSBuffer != 0);

        assert(_pObject != 0);

        pObject = static_cast<CObject*>(_pObject);
        pMesh   = &(*pObject->m_MeshPtr);

        assert(pMesh                           != 0);
        assert(pMesh->m_pNativeVertexBuffer    != 0);
        assert(pMesh->m_pNativeIndexBuffer     != 0);
        assert(pMesh->m_NumberOfBytesPerVertex  > 0);
        assert(pMesh->m_NumberOfIndices         > 0);

        // -----------------------------------------------------------------------------
        // Activate the shader.
        // -----------------------------------------------------------------------------
        m_pNativeDevice->VSSetShader(pMesh->m_VertexShaderPtr->m_pNativeVertexShader);
        m_pNativeDevice->PSSetShader(pMesh->m_PixelShaderPtr ->m_pNativePixelShader );

        // -----------------------------------------------------------------------------
        // Check if the mesh has a texture.
        // -----------------------------------------------------------------------------
        if (pMesh->m_TexturePtr != 0)
        {
            // -----------------------------------------------------------------------------
            // Activate the texture on the GPU. Note that we set the texture to slot 0 as registered
            // in the shader file.
            // -----------------------------------------------------------------------------
            m_pNativeDevice->PSSetShaderResources(0, 1, &pMesh->m_TexturePtr->m_pNativeTextureView);

            // -----------------------------------------------------------------------------
            // Activate the sampler on the GPU. Note that we set the sampler to slot 0 as registered
            // in the shader file.
            // -----------------------------------------------------------------------------
            m_pNativeDevice->PSSetSamplers(0, 1, &m_pNativeSamplerState);
        }

        // -----------------------------------------------------------------------------
        // Tell the GPU how to interpret the vertices by activating the vertex layout.
        // -----------------------------------------------------------------------------
        m_pNativeDevice->IASetInputLayout(pMesh->m_InputLayoutPtr->m_pNativeInputLayout);

        // -----------------------------------------------------------------------------
        // Activate the vertex buffer on the GPU.
        // -----------------------------------------------------------------------------
        unsigned int Stride = pMesh->m_NumberOfBytesPerVertex;
        unsigned int Offset = 0;

        m_pNativeDevice->IASetVertexBuffers(0, 1, &pMesh->m_pNativeVertexBuffer, &Stride, &Offset);

        // -----------------------------------------------------------------------------
        // Activate the index buffer on the GPU.
        // -----------------------------------------------------------------------------
        m_pNativeDevice->IASetIndexBuffer(pMesh->m_pNativeIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

        // -----------------------------------------------------------------------------
        // Set the topology of our mesh.
        // -----------------------------------------------------------------------------
        m_pNativeDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

        // -----------------------------------------------------------------------------
        // Define the position of the object in the world and upload it to the GPU.
        // -----------------------------------------------------------------------------
        m_pNativePerDrawCallVSBuffer->Map(D3D10_MAP_WRITE_DISCARD, NULL, reinterpret_cast<void**>(&pPerDrawCallVSBuffer));

        pPerDrawCallVSBuffer->m_WorldMatrix = pObject->m_WorldMatrix;

        m_pNativePerDrawCallVSBuffer->Unmap();

        // -----------------------------------------------------------------------------
        // Render the mesh.
        // -----------------------------------------------------------------------------
        m_pNativeDevice->DrawIndexed(pMesh->m_NumberOfIndices, 0, 0);

        // -----------------------------------------------------------------------------
        // If the mesh has a texture then deactivate the texture again.
        // -----------------------------------------------------------------------------
        if (pMesh->m_TexturePtr != 0)
        {
            pNativeTextureView = 0;

            m_pNativeDevice->PSSetShaderResources(0, 1, &pNativeTextureView);
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    void CYoshiX::SetWorldMatrix(BHandle _pObject, const float* _pMatrix)
    {
        CInternObject* pObject;

        assert(_pObject != 0);
        assert(_pMatrix != 0);

        pObject = static_cast<CInternObject*>(_pObject);

        memcpy(pObject->m_WorldMatrix, _pMatrix, sizeof(pObject->m_WorldMatrix));
    }

    // -----------------------------------------------------------------------------

    void CYoshiX::SetViewMatrix(const float* _pMatrix)
    {
        assert(_pMatrix != 0);

        memcpy(&m_ViewMatrix, _pMatrix, sizeof(m_ViewMatrix));
    }

    // -----------------------------------------------------------------------------

    void CYoshiX::SetProjectionMatrix(const float* _pMatrix)
    {
        assert(_pMatrix != 0);

        memcpy(&m_ProjectionMatrix, _pMatrix, sizeof(m_ViewMatrix));
    }

    // -----------------------------------------------------------------------------

    void CYoshiX::SetLightPosition(const float* _pPosition)
    {
        assert(_pPosition != 0);

        memcpy(m_Light.m_Position, _pPosition, sizeof(m_Light.m_Position));
    }

    // -----------------------------------------------------------------------------

    void CYoshiX::SetLightColor(const float* _pAmbientColor, const float* _pDiffuseColor, const float* _pSpecularColor, float _SpecularExponent)
    {
        assert(_pAmbientColor  != 0);
        assert(_pDiffuseColor  != 0);
        assert(_pSpecularColor != 0);

        memcpy(m_Light.m_AmbientColor , _pAmbientColor , sizeof(m_Light.m_AmbientColor ));
        memcpy(m_Light.m_DiffuseColor , _pDiffuseColor , sizeof(m_Light.m_DiffuseColor ));
        memcpy(m_Light.m_SpecularColor, _pSpecularColor, sizeof(m_Light.m_SpecularColor));

        m_Light.m_LightSpecularExponent = _SpecularExponent;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::OnResizeWindow()
    {
        int                     Width;
        int                     Height;

        HRESULT                 Result;
        RECT                    ViewRectangle;

        ID3D10Texture2D*        pNativeColorBuffer;
        ID3D10RenderTargetView* pNativeColorBufferView;
        ID3D10Texture2D*        pNativeDepthBuffer;
        ID3D10DepthStencilView* pNativeDepthBufferView;

        if ((m_pNativeDevice != 0) && (m_pNativeSwapChain != 0))
        {
            try
            {
                // -----------------------------------------------------------------------------
                // Set the interfaces to 0 for safe release in case of an exception.
                // -----------------------------------------------------------------------------
                pNativeColorBuffer     = 0;
                pNativeColorBufferView = 0;
                pNativeDepthBuffer     = 0;
                pNativeDepthBufferView = 0;

                // -----------------------------------------------------------------------------
                // Make sure that the old color buffer and depth buffer is not longer active.
                // -----------------------------------------------------------------------------
                m_pNativeDevice->OMSetRenderTargets(0, 0, 0);

                // -----------------------------------------------------------------------------
                // Release all size dependent resources.
                // -----------------------------------------------------------------------------
                SAFE_RELEASE(m_pNativeColorBuffer    );
                SAFE_RELEASE(m_pNativeDepthBuffer    );
                SAFE_RELEASE(m_pNativeColorBufferView);
                SAFE_RELEASE(m_pNativeDepthBufferView);

                // -----------------------------------------------------------------------------
                // Get the size of the render area.
                // -----------------------------------------------------------------------------
                GetClientRect(m_pNativeWindow, &ViewRectangle);

                Width  = ViewRectangle.right  - ViewRectangle.left;
                Height = ViewRectangle.bottom - ViewRectangle.top;

                // -----------------------------------------------------------------------------
                // Set the color buffer to the new size.
                // -----------------------------------------------------------------------------
                Result = m_pNativeSwapChain->ResizeBuffers(1, Width, Height, DXGI_FORMAT_R8G8B8A8_UNORM, 0);

                if (Result != S_OK)
                {
                    throw std::exception("Failed to resize the swap chain.");
                }

                // -----------------------------------------------------------------------------
                // Get the back buffer of the swap chain and make it to the render target, i.e.
                // to the color buffer, in which we want to render our scene.
                // -----------------------------------------------------------------------------
                Result = m_pNativeSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&pNativeColorBuffer));

                if (Result != S_OK)
                {
                    throw std::exception("Failed to create the color buffer.");
                }

                // -----------------------------------------------------------------------------
                // Create a view to our color buffer. A view is a class, which defines the way
                // we want to interpret the data in our buffer.
                // -----------------------------------------------------------------------------
                Result = m_pNativeDevice->CreateRenderTargetView(pNativeColorBuffer, 0, &pNativeColorBufferView);

                if (Result != S_OK)
                {
                    throw std::exception("Failed to create the color buffer view.");
                }

                // -----------------------------------------------------------------------------
                // Create the depth buffer.
                // -----------------------------------------------------------------------------
                D3D10_TEXTURE2D_DESC NativeDepthStencilTextureDescriptor;

                NativeDepthStencilTextureDescriptor.Width              = Width;
                NativeDepthStencilTextureDescriptor.Height             = Height;
                NativeDepthStencilTextureDescriptor.MipLevels          = 1;
                NativeDepthStencilTextureDescriptor.ArraySize          = 1;
                NativeDepthStencilTextureDescriptor.Format             = DXGI_FORMAT_D32_FLOAT;
                NativeDepthStencilTextureDescriptor.SampleDesc.Count   = 1;
                NativeDepthStencilTextureDescriptor.SampleDesc.Quality = 0;
                NativeDepthStencilTextureDescriptor.Usage              = D3D10_USAGE_DEFAULT;
                NativeDepthStencilTextureDescriptor.BindFlags          = D3D10_BIND_DEPTH_STENCIL;
                NativeDepthStencilTextureDescriptor.CPUAccessFlags     = 0;
                NativeDepthStencilTextureDescriptor.MiscFlags          = 0;

                Result = m_pNativeDevice->CreateTexture2D(&NativeDepthStencilTextureDescriptor, 0, &pNativeDepthBuffer);

                if (Result != S_OK)
                {
                    throw std::exception("Failed to create the depth buffer.");
                }

                D3D10_DEPTH_STENCIL_VIEW_DESC NativeDepthStencilDescriptor;

                NativeDepthStencilDescriptor.Format             = NativeDepthStencilTextureDescriptor.Format;
                NativeDepthStencilDescriptor.ViewDimension      = D3D10_DSV_DIMENSION_TEXTURE2D;
                NativeDepthStencilDescriptor.Texture2D.MipSlice = 0;

                Result = m_pNativeDevice->CreateDepthStencilView(pNativeDepthBuffer, &NativeDepthStencilDescriptor, &pNativeDepthBufferView);

                if (Result != S_OK)
                {
                    throw std::exception("Failed to create the depth buffer view.");
                }

                // -----------------------------------------------------------------------------
                // Tell DirectX, that it shall render the scene to our color buffer.
                // -----------------------------------------------------------------------------
                m_pNativeDevice->OMSetRenderTargets(1, &pNativeColorBufferView, pNativeDepthBufferView);

                // -----------------------------------------------------------------------------
                // Set the view port.
                // -----------------------------------------------------------------------------
                SetViewPort(Width, Height);

                // -----------------------------------------------------------------------------
                // We are safe now so set the members.
                // -----------------------------------------------------------------------------
                m_Width                  = Width;
                m_Height                 = Height;
                m_pNativeColorBuffer     = pNativeColorBuffer;
                m_pNativeColorBufferView = pNativeColorBufferView;
                m_pNativeDepthBuffer     = pNativeDepthBuffer;
                m_pNativeDepthBufferView = pNativeDepthBufferView;
            }
            catch (const std::exception& _rException)
            {
                SAFE_RELEASE(pNativeDepthBufferView);
                SAFE_RELEASE(pNativeDepthBuffer    );
                SAFE_RELEASE(pNativeColorBufferView);
                SAFE_RELEASE(pNativeColorBuffer    );

                WriteErrorMessage(_rException.what());

                return false;
            }
        }

        return true;
    }

    // -----------------------------------------------------------------------------

    bool CYoshiX::SetViewPort(int _Width, int _Height)
    {
        D3D10_VIEWPORT NativeViewPort;

        assert(m_pNativeDevice != 0);

        NativeViewPort.Width    = _Width;
        NativeViewPort.Height   = _Height;
        NativeViewPort.MinDepth = 0.0f;
        NativeViewPort.MaxDepth = 1.0f;
        NativeViewPort.TopLeftX = 0;
        NativeViewPort.TopLeftY = 0;

        m_pNativeDevice->RSSetViewports(1, &NativeViewPort);

        return true;
    }

    // -----------------------------------------------------------------------------

    void CYoshiX::BeginFrame()
    {
        SPerFrameVSBuffer* pPerFrameVSBuffer;
        SPerFramePSBuffer* pPerFramePSBuffer;
        D3DXMATRIX         InverseViewMatrix;
        ID3D10Buffer*      pNativeConstantBuffers[2];

        assert(m_pNativeDevice              != 0);
        assert(m_pNativeColorBufferView     != 0);
        assert(m_pNativeDepthBufferView     != 0);
        assert(m_pNativePerFrameVSBuffer    != 0);
        assert(m_pNativePerFramePSBuffer    != 0);
        assert(m_pNativePerDrawCallVSBuffer != 0);

        // -----------------------------------------------------------------------------
        // Clear the color buffer with the given color. The color is defined by the four
        // color components red, green, blue, and alpha. Color components can be defined
        // from 0.0 to 1.0.
        // -----------------------------------------------------------------------------
        m_pNativeDevice->ClearRenderTargetView(m_pNativeColorBufferView, m_ClearColor);

        // -----------------------------------------------------------------------------
        // Clear the depth buffer and the stencil buffer with the given values. Usually
        // the clear value of the depth buffer is 1.0, which represents the farthest 
        // possible distance of a visible pixel. So when we render an element inside of
        // the view area it should have depth values less than 1.0 to become visible.
        // -----------------------------------------------------------------------------
        m_pNativeDevice->ClearDepthStencilView(m_pNativeDepthBufferView, D3D10_CLEAR_DEPTH, 1.0f, 0);

        // -----------------------------------------------------------------------------
        // Upload the per frame vertex shader constants to the GPU.
        // -----------------------------------------------------------------------------
        D3DXMatrixInverse(&InverseViewMatrix, 0, &m_ViewMatrix);

        m_pNativePerFrameVSBuffer->Map(D3D10_MAP_WRITE_DISCARD, NULL, reinterpret_cast<void**>(&pPerFrameVSBuffer));

        pPerFrameVSBuffer->m_EyePosition.x = InverseViewMatrix._41;
        pPerFrameVSBuffer->m_EyePosition.y = InverseViewMatrix._42;
        pPerFrameVSBuffer->m_EyePosition.z = InverseViewMatrix._43;
        pPerFrameVSBuffer->m_LightPosition = m_Light.m_Position;

        D3DXMatrixMultiply(&pPerFrameVSBuffer->m_ViewProjectionMatrix, &m_ViewMatrix, &m_ProjectionMatrix);

        m_pNativePerFrameVSBuffer->Unmap();

        // -----------------------------------------------------------------------------
        // Upload the per frame pixel shader constants to the GPU.
        // -----------------------------------------------------------------------------
        m_pNativePerFramePSBuffer->Map(D3D10_MAP_WRITE_DISCARD, NULL, reinterpret_cast<void**>(&pPerFramePSBuffer));

        pPerFramePSBuffer->m_LightAmbientColor     = m_Light.m_AmbientColor;
        pPerFramePSBuffer->m_LightDiffuseColor     = m_Light.m_DiffuseColor;
        pPerFramePSBuffer->m_LightSpecularColor    = m_Light.m_SpecularColor;
        pPerFramePSBuffer->m_LightSpecularExponent = m_Light.m_LightSpecularExponent;

        m_pNativePerFramePSBuffer->Unmap();

        // -----------------------------------------------------------------------------
        // Activate the constant buffers on the GPU.
        // -----------------------------------------------------------------------------
        pNativeConstantBuffers[0] = m_pNativePerFrameVSBuffer;
        pNativeConstantBuffers[1] = m_pNativePerDrawCallVSBuffer;

        m_pNativeDevice->VSSetConstantBuffers(0, 2, pNativeConstantBuffers);

        pNativeConstantBuffers[0] = m_pNativePerFramePSBuffer;

        m_pNativeDevice->PSSetConstantBuffers(0, 1, pNativeConstantBuffers);
    }

    // -----------------------------------------------------------------------------

    void CYoshiX::EndFrame()
    {
        assert(m_pNativeSwapChain != 0);

        // -----------------------------------------------------------------------------
        // Make the back buffer visible.
        // -----------------------------------------------------------------------------
        m_pNativeSwapChain->Present(0, 0);
    }
} // namespace

////////////////////////////////////////////////////////////////////////////////
/// \namespace gfx
///
/// \brief Encapsulates all types and methods of the YoshiX frame work.
///
/// Encapsulates all types and methods of the YoshiX frame work.
///
/// \warning Do not declare using statements in a header file.
////////////////////////////////////////////////////////////////////////////////
namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool OpenWindow(int _Width, int _Height, const char* _pTitle)
    ///
    /// \brief Opens a window to render in.
    ///
    /// Opens a window to render in.
    ///
    /// \param _Width The width of the render area in pixels.
    /// \param _Height The height of the render area in pixels.
    /// \param _pTitle The title of the window represented by a '\0' terminated C-string.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool OpenWindow(int _Width, int _Height, const char* _pTitle)
    {
        return CYoshiX::GetInstance().OpenWindow(_Width, _Height, _pTitle);
    }

    // -----------------------------------------------------------------------------

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CloseWindow()
    ///
    /// \brief Closes the window.
    ///
    /// Closes the window and frees the resources associated with this window.
    ///
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CloseWindow()
    {
        return CYoshiX::GetInstance().CloseWindow();
    }

    // -----------------------------------------------------------------------------

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool StartupDirectX()
    ///
    /// \brief Starts up the DirectX render pipeline.
    ///
    /// Starts the DirectX render pipeline.
    ///
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool StartupDirectX()
    {
        return CYoshiX::GetInstance().StartupDirectX();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool ShutdownDirectX()
    ///
    /// \brief Shuts down the DirectX render pipeline.
    ///
    /// Shuts down the DirectX render pipeline and releases all resources associated
    /// with it.
    ///
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool ShutdownDirectX()
    {
        return CYoshiX::GetInstance().ShutdownDirectX();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool RunApplication(IApplication* _pApplication)
    ///
    /// \brief Runs an application.
    ///
    /// Runs an application, i.e. calls the callback methods defined by the 
    /// IApplication class.
    ///
    /// \param _pApplication A pointer to the application to be run.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool RunApplication(IApplication* _pApplication)
    {
        return CYoshiX::GetInstance().RunApplication(_pApplication);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool SetDepthTest(bool _Flag)
    ///
    /// \brief Activates or deactivates the depth test.
    ///
    /// Activates or deactivates the depth test.
    ///
    /// \param _Flag If true the depth test will be activated otherwise deactivated.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool SetDepthTest(bool _Flag)
    {
        return CYoshiX::GetInstance().SetDepthTest(_Flag);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool SetWireFrame(bool _Flag)
    ///
    /// \brief Activates or deactivates the wire frame mode.
    ///
    /// Activates or deactivates the wire frame mode. If activated meshes are 
    /// displayed as wire frames.
    ///
    /// \param _Flag If true meshes are displayed as wire frames otherwise as solid surfaces.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool SetWireFrame(bool _Flag)
    {
        return CYoshiX::GetInstance().SetWireFrame(_Flag);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn void SetClearColor(const float* _pColor)
    ///
    /// \brief Defines the background color of the window.
    ///
    /// Defines the background color of the window. The window is automatically 
    /// cleared with this color at the begin of each frame. Colors are defined by an
    /// array of 4 float values representing the RGBA channels.
    ///
    /// \param _pColor The background color defined by 4 float values.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    void SetClearColor(const float* _pColor)
    {
        return CYoshiX::GetInstance().SetClearColor(_pColor);
    }
} // namespace gfx

namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CreateTexture(const char* _pPath, BHandle* _ppTexture)
    ///
    /// \brief Creates a new texture.
    ///
    /// Creates a new texture. The texture is represented by a handle which is
    /// returned in the last argument.
    ///
    /// \param _pPath The file path of the texture.
    /// \param _ppTexture A pointer to a texture handle which is filled by the method with a valid texture handle.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CreateTexture(const char* _pPath, BHandle* _ppTexture)
    {
        return CYoshiX::GetInstance().CreateTexture(_pPath, _ppTexture);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool ReleaseTexture(BHandle _pTexture)
    ///
    /// \brief Frees the resources of a texture.
    ///
    /// Call this method on each texture created via CreateTexture to free its 
    /// resources again.
    ///
    /// \param _pTexture The handle to the texture.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool ReleaseTexture(BHandle _pTexture)
    {
        return CYoshiX::GetInstance().ReleaseTexture(_pTexture);
    }
} // namespace gfx

namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CreateMesh(const float* _pVertices, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    ///
    /// \brief Creates a new mesh with a default material.
    ///
    /// A mesh is a set of triangles. The vertices of the mesh are defined in local
    /// space. Each vertex is represented by an array of 3 float values. The topology
    /// of the mesh is defined by triangles. Each triangle is represented by three 
    /// integer indices, where an index corresponds to the position of a vertex in
    /// the vertex array. The mesh is represented by a handle which is returned in
    /// the last argument.
    /// 
    /// The default material describes a gray-color, non-lighted surface.
    ///
    /// \param _pVertices The vertex array containing 3 float values for each vertex.
    /// \param _NumberOfVertices The number of vertices.
    /// \param _pIndices The number of vertices.
    /// \param _NumberOfIndices The number of vertices.
    /// \param _ppMesh A pointer to a mesh handle which is filled by the method with a valid mesh handle.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CreateMesh(const float* _pVertices, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    {
        return CYoshiX::GetInstance().CreateMesh(_pVertices, _NumberOfVertices, _pIndices, _NumberOfIndices, _ppMesh);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CreateMesh(const float* _pVertices, const float* _pNormals, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    ///
    /// \brief Creates a new mesh with a lighted default material.
    ///
    /// A mesh is a set of triangles. The vertices of the mesh are defined in local
    /// space. Each vertex is represented by an array of 3 float values. The topology
    /// of the mesh is defined by triangles. Each triangle is represented by three 
    /// integer indices, where an index corresponds to the position of a vertex in
    /// the vertex array. The mesh is represented by a handle which is returned in
    /// the last argument.
    /// 
    /// The lighted default material describes a gray-color, lighted surface. To
    /// light a surface the normals of the mesh have to be defined. Normals are
    /// passed on a per vertex basis, so the size of the normal array has to match
    /// the size of the vertex array.
    ///
    /// \param _pVertices The vertex array containing 3 float values for each vertex.
    /// \param _pNormals The normal array containing 3 float values for each normal.
    /// \param _NumberOfVertices The number of vertices.
    /// \param _pIndices The number of vertices.
    /// \param _NumberOfIndices The number of vertices.
    /// \param _ppMesh A pointer to a mesh handle which is filled by the method with a valid mesh handle.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CreateMesh(const float* _pVertices, const float* _pNormals, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    {
        return CYoshiX::GetInstance().CreateMesh(_pVertices, _pNormals, _NumberOfVertices, _pIndices, _NumberOfIndices, _ppMesh);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CreateColoredMesh(const float* _pVertices, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    ///
    /// \brief Creates a new mesh with a colored material.
    ///
    /// A mesh is a set of triangles. The vertices of the mesh are defined in local
    /// space. Each vertex is represented by an array of 3 float values. The topology
    /// of the mesh is defined by triangles. Each triangle is represented by three 
    /// integer indices, where an index corresponds to the position of a vertex in
    /// the vertex array. The mesh is represented by a handle which is returned in
    /// the last argument.
    /// 
    /// The colored material describes a colored, non-lighted surface. Colors are
    /// passed on a per vertex basis, so the size of the color array has to match
    /// the size of the vertex array.
    ///
    /// \param _pVertices The vertex array containing 3 float values for each vertex.
    /// \param _pColors The color array containing 4 float values for each color.
    /// \param _NumberOfVertices The number of vertices.
    /// \param _pIndices The number of vertices.
    /// \param _NumberOfIndices The number of vertices.
    /// \param _ppMesh A pointer to a mesh handle which is filled by the method with a valid mesh handle.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CreateColoredMesh(const float* _pVertices, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    {
        return CYoshiX::GetInstance().CreateColoredMesh(_pVertices, _pColors, _NumberOfVertices, _pIndices, _NumberOfIndices, _ppMesh);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CreateColoredMesh(const float* _pVertices, const float* _pNormals, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    ///
    /// \brief Creates a new mesh with a lighted colored material.
    ///
    /// A mesh is a set of triangles. The vertices of the mesh are defined in local
    /// space. Each vertex is represented by an array of 3 float values. The topology
    /// of the mesh is defined by triangles. Each triangle is represented by three 
    /// integer indices, where an index corresponds to the position of a vertex in
    /// the vertex array. The mesh is represented by a handle which is returned in
    /// the last argument.
    /// 
    /// The lighted colored material describes a colored, lighted surface. To light
    /// a surface the normals of the mesh have to be defined. Normals are passed
    /// on a per vertex basis, so the size of the normal array has to match the size
    /// of the vertex array. Colors are also passed on a per vertex basis, so the 
    /// size of the color array has to match the size of the vertex array.
    ///
    /// \param _pVertices The vertex array containing 3 float values for each vertex.
    /// \param _pNormals The normal array containing 3 float values for each normal.
    /// \param _pColors The color array containing 4 float values for each color.
    /// \param _NumberOfVertices The number of vertices.
    /// \param _pIndices The number of vertices.
    /// \param _NumberOfIndices The number of vertices.
    /// \param _ppMesh A pointer to a mesh handle which is filled by the method with a valid mesh handle.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CreateColoredMesh(const float* _pVertices, const float* _pNormals, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh)
    {
        return CYoshiX::GetInstance().CreateColoredMesh(_pVertices, _pNormals, _pColors, _NumberOfVertices, _pIndices, _NumberOfIndices, _ppMesh);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CreateTexturedMesh(const float* _pVertices, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh)
    ///
    /// \brief Creates a new mesh with a textured material.
    ///
    /// A mesh is a set of triangles. The vertices of the mesh are defined in local
    /// space. Each vertex is represented by an array of 3 float values. The topology
    /// of the mesh is defined by triangles. Each triangle is represented by three 
    /// integer indices, where an index corresponds to the position of a vertex in
    /// the vertex array. The mesh is represented by a handle which is returned in
    /// the last argument.
    /// 
    /// The texture material describes a textured, non-lighted surface. The user
    /// has to pass a texture handle and an array of texture coordinates. Texture
    /// coordinates are passed on a per vertex basis, so the size of the texture
    /// coordinate array has to match the size of the vertex array.
    ///
    /// \param _pVertices The vertex array containing 3 float values for each vertex.
    /// \param _pTexCoords The texture coordinate array containing 2 float values for each coordinate.
    /// \param _NumberOfVertices The number of vertices.
    /// \param _pIndices The number of vertices.
    /// \param _NumberOfIndices The number of vertices.
    /// \param _pTexture A handle to a texture.
    /// \param _ppMesh A pointer to a mesh handle which is filled by the method with a valid mesh handle.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CreateTexturedMesh(const float* _pVertices, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh)
    {
        return CYoshiX::GetInstance().CreateTexturedMesh(_pVertices, _pTexCoords, _NumberOfVertices, _pIndices, _NumberOfIndices, _pTexture, _ppMesh);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CreateTexturedMesh(const float* _pVertices, const float* _pNormals, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh)
    ///
    /// \brief Creates a new mesh with a lighted textured material.
    ///
    /// A mesh is a set of triangles. The vertices of the mesh are defined in local
    /// space. Each vertex is represented by an array of 3 float values. The topology
    /// of the mesh is defined by triangles. Each triangle is represented by three 
    /// integer indices, where an index corresponds to the position of a vertex in
    /// the vertex array. The mesh is represented by a handle which is returned in
    /// the last argument.
    /// 
    /// The lighted texture material describes a textured, lighted surface. To light
    /// a surface the normals of the mesh have to be defined. Normals are passed
    /// on a per vertex basis, so the size of the normal array has to match the size
    /// of the vertex array. The user also has to pass a texture handle and an array
    /// of texture coordinates. Texture coordinates are passed on a per vertex basis,
    /// so the size of the texture coordinates array has to match the size of the
    /// vertex array.
    ///
    /// \param _pVertices The vertex array containing 3 float values for each vertex.
    /// \param _pNormals The normal array containing 3 float values for each normal.
    /// \param _pTexCoords The texture coordinate array containing 2 float values for each coordinate.
    /// \param _NumberOfVertices The number of vertices.
    /// \param _pIndices The number of vertices.
    /// \param _NumberOfIndices The number of vertices.
    /// \param _pTexture A handle to a texture.
    /// \param _ppMesh A pointer to a mesh handle which is filled by the method with a valid mesh handle.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CreateTexturedMesh(const float* _pVertices, const float* _pNormals, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh)
    {
        return CYoshiX::GetInstance().CreateTexturedMesh(_pVertices, _pNormals, _pTexCoords, _NumberOfVertices, _pIndices, _NumberOfIndices, _pTexture, _ppMesh);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool ReleaseMesh(BHandle _pMesh)
    ///
    /// \brief Frees the resources of a mesh.
    ///
    /// Call this method on a mesh to free its resources again. A mesh is only 
    /// allowed to be freed, when is is not longer referenced by objects.
    ///
    /// \param _pMesh The handle to the mesh.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool ReleaseMesh(BHandle _pMesh)
    {
        return CYoshiX::GetInstance().ReleaseMesh(_pMesh);
    }
} // namespace gfx

namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool CreateObject(BHandle _pMesh, BHandle* _ppObject)
    ///
    /// \brief Creates a new object and associate a mesh with it.
    ///
    /// Creates a new object and associate a mesh with it. The object is represented
    /// by a handle which is returned in the last argument.
    ///
    /// \param _pMesh The handle to the object.
    /// \param _ppObject A pointer to an object handle which is filled by the method with a valid object handle.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool CreateObject(BHandle _pMesh, BHandle* _ppObject)
    {
        return CYoshiX::GetInstance().CreateObject(_pMesh, _ppObject);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool ReleaseObject(BHandle _pObject)
    ///
    /// \brief Frees the resources of an object.
    ///
    /// Call this method on each object created via CreateObject to free its 
    /// resources again.
    ///
    /// \param _pObject The handle to the object.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool ReleaseObject(BHandle _pObject)
    {
        return CYoshiX::GetInstance().ReleaseObject(_pObject);
    }
} // namespace gfx

namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool DrawObject(BHandle _pObject)
    ///
    /// \brief Visualizes an object.
    ///
    /// Visualizes an object.
    /// 
    /// \param _pObject The handle to the object.
    /// \return true if successful otherwise false.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    bool DrawObject(BHandle _pObject)
    {
        return CYoshiX::GetInstance().DrawObject(_pObject);
    }
} // namespace gfx

namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \fn void SetWorldMatrix(BHandle _pObject, const float* _pMatrix)
    ///
    /// \brief Defines the world space transformation of a single object.
    ///
    /// Defines the world space transformation of a single object. The 
    /// transformation is represented by a 4x4 matrix.
    ///
    /// \param _pObject The handle to the object.
    /// \param _pMatrix The world matrix of the object with 16 float values.
    /// \warning Matrices are in row-major order.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    void SetWorldMatrix(BHandle _pObject, const float* _pMatrix)
    {
        CYoshiX::GetInstance().SetWorldMatrix(_pObject, _pMatrix);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn void SetViewMatrix(const float* _pMatrix)
    ///
    /// \brief Defines the transformation from world space into view space.
    ///
    /// Defines the current active view matrix, which is used the render pipeline to
    /// transform the objects from world space into view space.
    ///
    /// \param _pMatrix The projection matrix with 16 float values.
    /// \warning Matrices are in row-major order.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    void SetViewMatrix(const float* _pMatrix)
    {
        CYoshiX::GetInstance().SetViewMatrix(_pMatrix);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn void SetProjectionMatrix(const float* _pMatrix)
    ///
    /// \brief Defines the transformation from view space into clip space.
    ///
    /// Defines the current active projection matrix, which is used the render
    /// pipeline to transform the objects from view space into clip space.
    ///
    /// \param _pMatrix The projection matrix with 16 float values.
    /// \warning Matrices are in row-major order.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    void SetProjectionMatrix(const float* _pMatrix)
    {
        CYoshiX::GetInstance().SetProjectionMatrix(_pMatrix);
    }
} // namespace gfx

namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \fn void SetLightPosition(const float* _pPosition)
    ///
    /// \brief Defines the position of the light source in world space.
    ///
    /// Defines the position of the light source in world space. The position is
    /// passed as an array of 3 float values.
    ///
    /// \param _pPosition The light position with 3 float values.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    void SetLightPosition(const float* _pPosition)
    {
        CYoshiX::GetInstance().SetLightPosition(_pPosition);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn void SetLightColor(const float* _pAmbientColor, const float* _pDiffuseColor, const float* _pSpecularColor, float _SpecularExponent)
    ///
    /// \brief Defines the properties of the light source.
    ///
    /// Defines the properties of the light source. The 3 colors are passed as
    /// arrays of 4 float values. See the Phong and Blinn lighting equations for
    /// better understanding. Specular reflection is calculated by the Blinn
    /// equation.
    ///
    /// \param _pAmbientColor The ambient color of the light source with 4 float values.
    /// \param _pDiffuseColor The diffuse color of the light source with 4 float values.
    /// \param _pSpecularColor The specular color of the light source with 4 float values.
    /// \param _SpecularExponent The specular exponent of the Blinn equation.
    /// \warning Not thread-safe.
    ////////////////////////////////////////////////////////////////////////////////
    void SetLightColor(const float* _pAmbientColor, const float* _pDiffuseColor, const float* _pSpecularColor, float _SpecularExponent)
    {
        CYoshiX::GetInstance().SetLightColor(_pAmbientColor, _pDiffuseColor, _pSpecularColor, _SpecularExponent);
    }
} // namespace gfx

namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetNormalizedVector(const float* _pVector, float* _pResultVector)
    ///
    /// \brief Normalizes the a 3D vector to the length 1.
    ///
    /// Takes an array of 3 float values as input and normalizes it to the length
    /// 1. The result is stored in the last argument, which is an array of 3 float
    /// values allocated by the user.
    ///
    /// \param _pVector The input vector with 3 float values.
    /// \param _pResultVector The output vector with 3 float values.
    /// \return A pointer to the output vector.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetNormalizedVector(const float* _pVector, float* _pResultVector)
    {
        assert(_pVector       != 0);
        assert(_pResultVector != 0);

        return reinterpret_cast<float*>(D3DXVec3Normalize(reinterpret_cast<D3DXVECTOR3*>(_pResultVector), reinterpret_cast<const D3DXVECTOR3*>(_pVector)));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* TransformVector(const float* _pVector, const float* _pMatrix, float* _pResultVector)
    ///
    /// \brief Transforms a 3D vector by a 4x4 matrix.
    ///
    /// Takes an array of 3 float values as input and transforms it by a 4x4 matrix
    /// containing 16 float values. The result is stored in the last argument, which
    /// is an array of 3 float values allocated by the user.
    /// 
    ///     V' = V * M
    ///
    /// \param _pVector The input vector with 3 float values.
    /// \param _pMatrix The matrix with 16 float values.
    /// \param _pResultVector The output vector with 3 float values.
    /// \return A pointer to the output vector.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* TransformVector(const float* _pVector, const float* _pMatrix, float* _pResultVector)
    {
        D3DXVECTOR4 ResultVector;

        assert(_pVector       != 0);
        assert(_pMatrix       != 0);
        assert(_pResultVector != 0);

        reinterpret_cast<float*>(D3DXVec3Transform(&ResultVector, reinterpret_cast<const D3DXVECTOR3*>(_pVector), reinterpret_cast<const D3DXMATRIX*>(_pMatrix)));

        assert(::fabsf(ResultVector.w) > 0.000001f);

        _pResultVector[0] = ResultVector.x / ResultVector.w;
        _pResultVector[1] = ResultVector.y / ResultVector.w;
        _pResultVector[2] = ResultVector.z / ResultVector.w;

        return _pResultVector;
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* MulMatrix(const float* _pLeftMatrix, const float* _pRightMatrix, float* _pResultMatrix)
    ///
    /// \brief Multiplies two 4x4 matrices.
    ///
    /// Takes a left and a right 4x4 matrix and multiplies them. Matrices are passed
    /// an array of 16 float values. The result is stored in the last argument, 
    /// which is an array of 16 float values allocated by the user.
    /// 
    ///     M = L * R
    ///
    /// \param _pLeftMatrix The left input matrix with 16 float values.
    /// \param _pRightMatrix The right input matrix with 16 float values.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* MulMatrix(const float* _pLeftMatrix, const float* _pRightMatrix, float* _pResultMatrix)
    {
        assert(_pLeftMatrix   != 0);
        assert(_pRightMatrix  != 0);
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixMultiply(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), reinterpret_cast<const D3DXMATRIX*>(_pLeftMatrix), reinterpret_cast<const D3DXMATRIX*>(_pRightMatrix)));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetTranslationMatrix(float _X, float _Y, float _Z, float* _pResultMatrix)
    ///
    /// \brief Returns the 4x4 translation matrix.
    ///
    /// Takes a translation 3D vector and returns the corresponding 4x4 translation
    /// matrix. The result is stored in the last argument, which is an array of 16
    /// float values allocated by the user.
    ///
    /// \param _X The translation along the x-axis.
    /// \param _Y The translation along the y-axis.
    /// \param _Z The translation along the z-axis.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetTranslationMatrix(float _X, float _Y, float _Z, float* _pResultMatrix)
    {
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixTranslation(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), _X, _Y, _Z));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetScaleMatrix(float _Scalar, float* _pResultMatrix)
    ///
    /// \brief Returns the 4x4 uniform scaling matrix.
    ///
    /// Takes a scaling factor and returns the corresponding 4x4 uniform scaling
    /// matrix. The result is stored in the last argument, which is an array of 16
    /// float values allocated by the user.
    ///
    /// \param _Scalar The scaling factor.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetScaleMatrix(float _Scalar, float* _pResultMatrix)
    {
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixScaling(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), _Scalar, _Scalar, _Scalar));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetScaleMatrix(float _ScalarX, float _ScalarY, float _ScalarZ, float* _pResultMatrix)
    ///
    /// \brief Returns the 4x4 scaling matrix.
    ///
    /// Takes 3 scaling factors and returns the corresponding 4x4 scaling matrix.
    /// The result is stored in the last argument, which is an array of 16 float
    /// values allocated by the user.
    ///
    /// \param _ScalarX The scaling factor along the x-axis.
    /// \param _ScalarY The scaling factor along the y-axis.
    /// \param _ScalarZ The scaling factor along the z-axis.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetScaleMatrix(float _ScalarX, float _ScalarY, float _ScalarZ, float* _pResultMatrix)
    {
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixScaling(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), _ScalarX, _ScalarY, _ScalarZ));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetRotationXMatrix(float _Degrees, float* _pResultMatrix)
    ///
    /// \brief Returns the 4x4 rotation matrix around the x-axis.
    ///
    /// Takes an input angles in degrees and returns the corresponding 4x4 rotation
    /// matrix around the x-axis. The result is stored in the last argument, which
    /// is an array of 16 float values allocated by the user.
    /// 
    /// \param _Degrees The rotation angle around the x-axis in degrees.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetRotationXMatrix(float _Degrees, float* _pResultMatrix)
    {
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixRotationX(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), _Degrees * g_Pi / 180.0f));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetRotationYMatrix(float _Degrees, float* _pResultMatrix)
    ///
    /// \brief Returns the 4x4 rotation matrix around the y-axis.
    ///
    /// Takes an input angles in degrees and returns the corresponding 4x4 rotation
    /// matrix around the y-axis. The result is stored in the last argument, which
    /// is an array of 16 float values allocated by the user.
    /// 
    /// \param _Degrees The rotation angle around the y-axis in degrees.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetRotationYMatrix(float _Degrees, float* _pResultMatrix)
    {
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixRotationY(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), _Degrees * g_Pi / 180.0f));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetRotationZMatrix(float _Degrees, float* _pResultMatrix)
    ///
    /// \brief Returns the 4x4 rotation matrix around the z-axis.
    ///
    /// Takes an input angles in degrees and returns the corresponding 4x4 rotation
    /// matrix around the z-axis. The result is stored in the last argument, which
    /// is an array of 16 float values allocated by the user.
    /// 
    /// \param _Degrees The rotation angle around the z-axis in degrees.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetRotationZMatrix(float _Degrees, float* _pResultMatrix)
    {
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixRotationZ(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), _Degrees * g_Pi / 180.0f));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetViewMatrix(float* _pEye, float* _pAt, float* _pUp, float* _pResultMatrix)
    ///
    /// \brief Returns a 4x4 matrix to transform the world into view space.
    ///
    /// Takes the observer coordinate system to compute a look-at matrix, which
    /// transforms vertices from world space into view space. The observer 
    /// coordinate system is defined by 3 input vectors, all passed as an array
    /// of 3 float values. The eye vector defines the position of the observer in
    /// the world. The at vector defines a point in the world, where the observer
    /// is looking to. The at vector does not have to be normalized. The view
    /// direction is calculated by normalize(at - eye). The up vector defines
    /// the orientation of the observer around the view direction. The result is
    /// stored in the last argument, which is an array of 16 float values allocated
    /// by the user.
    /// 
    /// \param _pEye The world space position of the observer passed by 3 float values.
    /// \param _pAt A point in world space where the observer is looking at passed by 3 float values.
    /// \param _pUp The orientation of the observer around the view direction passed by 3 float values.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetViewMatrix(float* _pEye, float* _pAt, float* _pUp, float* _pResultMatrix)
    {
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixLookAtLH(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), reinterpret_cast<const D3DXVECTOR3*>(_pEye), reinterpret_cast<const D3DXVECTOR3*>(_pAt), reinterpret_cast<const D3DXVECTOR3*>(_pUp)));
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn float* GetProjectionMatrix(float _FieldOfViewY, float _AspectRatio, float _Near, float _Far, float* _pResultMatrix)
    ///
    /// \brief Returns a 4x4 matrix which defines the clip space transformation.
    /// 
    /// Defines the view frustum of the observer and returns the corresponding
    /// projection matrix. The projection matrix represents the transformation from
    /// view space into clip space. The view frustum is defined by 4 values, which
    /// are the field of view angle, the aspect ratio, the near clipping plane, 
    /// and the far clipping plane. The field of view angle is the angle spawned by
    /// the upper and the lower clipping plane of the view frustum. The angle is
    /// passed in degrees. The aspect ratio is defined by width / height of the
    /// window area. The dimensions width and height are measured in pixels. The 
    /// near value defines the distance from the observer's eye position to the
    /// near clipping plane. The far value defines the distance from the observer's
    /// eye position to the far clipping plane.
    ///
    ///
    /// \param _FieldOfViewY The angle spawned by upper and lower clipping plane in degrees.
    /// \param _AspectRatio The ratio between width and height of the window area.
    /// \param _Near The distance from the eye position to the near clipping plane.
    /// \param _Far The distance from the eye position to the far clipping plane.
    /// \param _pResultMatrix The output matrix with 16 float values.
    /// \return A pointer to the output matrix.
    /// \warning Matrices are in row-major order.
    ////////////////////////////////////////////////////////////////////////////////
    float* GetProjectionMatrix(float _FieldOfViewY, float _AspectRatio, float _Near, float _Far, float* _pResultMatrix)
    {
        assert(_pResultMatrix != 0);

        return reinterpret_cast<float*>(D3DXMatrixPerspectiveFovLH(reinterpret_cast<D3DXMATRIX*>(_pResultMatrix), _FieldOfViewY * g_Pi / 180.0f, _AspectRatio, _Near, _Far));
    }
} // namespace gfx

namespace gfx
{
    ////////////////////////////////////////////////////////////////////////////////
    /// \class IApplication
    ///
    /// \brief Defines an application which can be run by the render pipeline.
    /// 
    /// Defines a set of callback methods which are called by the YoshiX framework
    /// in case of certain situations. The user has to overload the private virtual
    /// functions of the class to define her wanted behavior. The public methods of
    /// the class are just stubs to call the corresponding private methods. See
    /// Scott Meyers, Effective C++, Item 35, page 171 why virtual functions should
    /// not be declared as public.
    /// 
    /// Though the class is named with the Prefix 'I' it is not an abstract class.
    /// The private methods are only virtual but not pure virtual functions. So the
    /// user has only to overload the methods, she is interested in.
    ////////////////////////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn IApplication::~IApplication()
    ///
    /// \brief Virtual destructor of the application.
    /// 
    /// Virtual destructor of the application.
    ////////////////////////////////////////////////////////////////////////////////
    IApplication::~IApplication()
    {
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnStartup()
    ///
    /// \brief Called by the frame work once after starting the application.
    /// 
    /// First method to be called after starting the application in the frame work.
    /// Overload the corresponding InternOnStartup method to setup properties and
    /// native resources of the application.
    /// 
    /// \return true if successful otherwise false.
    /// \warning Resources such as textures, meshes, and objects should be allocated in the resource matching callbacks.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnStartup()
    {
        return InternOnStartup();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnShutdown()
    ///
    /// \brief Called by the frame work once before shutting down the application.
    /// 
    /// Last method to be called when running the application in the frame work.
    /// Overload the corresponding InternOnShutdown method to free the native 
    /// resources of the application.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnShutdown()
    {
        return InternOnShutdown();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnCreateTextures()
    ///
    /// \brief Called by the frame work once after the OnStartup method.
    /// 
    /// Method called after the OnStartup method. Overload the corresponding 
    /// InternOnCreateTextures method to create texture resources in the frame work.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnCreateTextures()
    {
        return InternOnCreateTextures();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnReleaseTextures()
    ///
    /// \brief Called by the frame work once before the OnShutdown method.
    /// 
    /// Method called before the OnShutdown method. Overload the corresponding
    /// InternOnReleaseTextures method to release texture resources in the frame
    /// work again.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnReleaseTextures()
    {
        return InternOnReleaseTextures();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnCreateMeshes()
    ///
    /// \brief Called by the frame work once after the OnCreateTextures method.
    /// 
    /// Method called after the OnCreateTextures method. Overload the corresponding
    /// InternOnCreateMeshes method to create mesh resources in the frame work.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnCreateMeshes()
    {
        return InternOnCreateMeshes();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnReleaseMeshes()
    ///
    /// \brief Called by the frame work once before the OnReleaseTextures method.
    /// 
    /// Method called before the OnReleaseTextures method. Overload the 
    /// corresponding InternOnReleaseMeshes method to release mesh resources in the
    /// frame work again.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnReleaseMeshes()
    {
        return InternOnReleaseMeshes();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnCreateObjects()
    ///
    /// \brief Called by the frame work once after the OnCreateMeshes method.
    /// 
    /// Method called after the OnCreateMeshes method. Overload the corresponding
    /// InternOnCreateObjects method to create object resources in the frame work.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnCreateObjects()
    {
        return InternOnCreateObjects();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnReleaseObjects()
    ///
    /// \brief Called by the frame work once before the OnReleaseMeshes method.
    /// 
    /// Method called before the OnReleaseMeshes method. Overload the corresponding
    /// InternOnReleaseObjects method to release object resources in the frame work
    /// again.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnReleaseObjects()
    {
        return InternOnReleaseObjects();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnResize(int _Width, int _Height)
    ///
    /// \brief Called by the frame work whenever the window has been resized.
    /// 
    /// Method called after the window size has been changed. Overload the
    /// corresponding InternOnResize to modify all properties depending on the
    /// window size. Since a resize of the window usually modifies the aspect ratio
    /// this is the place to set the projection matrix in the frame work.
    /// 
    /// \param _Width New width of the window in pixels.
    /// \param _Height New height of the window in pixels.
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnResize(int _Width, int _Height)
    {
        return InternOnResize(_Width, _Height);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnKeyEvent(unsigned int _Key, bool _IsKeyDown, bool _IsAltDown)
    ///
    /// \brief Called by the frame work whenever a key has been pressed or released.
    /// 
    /// Called by the frame work whenever a key has been pressed or released. Overload
    /// the corresponding InternOnKeyEvent to listen to key events.
    /// 
    /// \param _Key The ASCII code of the affected key.
    /// \param _IsKeyDown true if the key has been pressed down, false if it has been released.
    /// \param _IsAltDown true if the ALT key is pressed down..
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnKeyEvent(unsigned int _Key, bool _IsKeyDown, bool _IsAltDown)
    {
        return InternOnKeyEvent(_Key, _IsKeyDown, _IsAltDown);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnMouseEvent()
    ///
    /// \brief Called by the frame work whenever the mouse state has been changed.
    /// 
    /// Called by the frame work whenever the mouse state has been changed. Overload
    /// the corresponding InternOnMouseEvent method to listen to mouse events. Mouse
    /// buttons are represented by an ID, where 0 represents the left button, 1 the
    /// middle button and 2 the right button.
    /// 
    /// \param _X The x-position of the mouse cursor.
    /// \param _Y The y-position of the mouse cursor.
    /// \param _Button The ID of the affected button.
    /// \param _IsButtonDown true if the button has been pressed down, false if it has been released.
    /// \param _IsDoubleClick true if the button was double clicked, otherwise false.
    /// \param _WheelDelta A value representing the relative mouse wheel modification.
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnMouseEvent(int _X, int _Y, int _Button, bool _IsButtonDown, bool _IsDoubleClick, int _WheelDelta)
    {
        return InternOnMouseEvent(_X, _Y, _Button, _IsButtonDown, _IsDoubleClick, _WheelDelta);
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnUpdate()
    ///
    /// \brief Called by the frame work once per frame to update the formal world state.
    /// 
    /// Method called once per frame before the OnFrame Method. Overload the 
    /// corresponding InternOnUpdate method to update the formal state of your
    /// world, e.g. camera position and orientation and object matrices.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnUpdate()
    {
        return InternOnUpdate();
    }

    ////////////////////////////////////////////////////////////////////////////////
    /// \fn bool IApplication::OnFrame()
    ///
    /// \brief Called by the frame work once per frame to render the world state.
    /// 
    /// Method called once per frame after the OnUpdate Method. Overload the 
    /// corresponding InternOnFrame method to draw the objects of your scene.
    /// 
    /// \return true if successful otherwise false.
    ////////////////////////////////////////////////////////////////////////////////
    bool IApplication::OnFrame()
    {
        return InternOnFrame();
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnStartup()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnShutdown()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnCreateTextures()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnReleaseTextures()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnCreateMeshes()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnReleaseMeshes()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnCreateObjects()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnReleaseObjects()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnResize(int _Width, int _Height)
    {
        UNUSED(_Width);
        UNUSED(_Height);

        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnKeyEvent(unsigned int _Key, bool _IsKeyDown, bool _IsAltDown)
    {
        UNUSED(_Key);
        UNUSED(_IsKeyDown);
        UNUSED(_IsAltDown);

        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnMouseEvent(int _X, int _Y, int _Button, bool _IsButtonDown, bool _IsDoubleClick, int _WheelDelta)
    {
        UNUSED(_X);
        UNUSED(_Y);
        UNUSED(_Button);
        UNUSED(_IsButtonDown);
        UNUSED(_IsDoubleClick);
        UNUSED(_WheelDelta);

        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnUpdate()
    {
        return true;
    }

    // -----------------------------------------------------------------------------

    bool IApplication::InternOnFrame()
    {
        return true;
    }
} // namespace gfx

#undef UNUSED
#undef SAFE_RELEASE
